diff --git a/Mage.Sets/src/mage/sets/betrayersofkamigawa/AkkiBlizzardHerder.java b/Mage.Sets/src/mage/sets/betrayersofkamigawa/AkkiBlizzardHerder.java new file mode 100644 index 0000000000..1a377a71bb --- /dev/null +++ b/Mage.Sets/src/mage/sets/betrayersofkamigawa/AkkiBlizzardHerder.java @@ -0,0 +1,71 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.betrayersofkamigawa; + +import java.util.UUID; + +import mage.Constants.CardType; +import mage.Constants.Rarity; +import mage.MageInt; +import mage.abilities.common.DiesTriggeredAbility; +import mage.abilities.effects.common.SacrificeAllEffect; +import mage.cards.CardImpl; +import mage.filter.common.FilterControlledPermanent; + +/** + * + * @author Loki + */ +public class AkkiBlizzardHerder extends CardImpl<AkkiBlizzardHerder> { + + private static final FilterControlledPermanent filter = new FilterControlledPermanent("land"); + static { + filter.getCardType().add(CardType.LAND); + } + + public AkkiBlizzardHerder(UUID ownerId) { + super(ownerId, 91, "Akki Blizzard-Herder", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{1}{R}"); + this.expansionSetCode = "BOK"; + this.subtype.add("Goblin"); + this.subtype.add("Shaman"); + this.color.setRed(true); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + // When Akki Blizzard-Herder dies, each player sacrifices a land. + this.addAbility(new DiesTriggeredAbility(new SacrificeAllEffect(filter))); + } + + public AkkiBlizzardHerder(final AkkiBlizzardHerder card) { + super(card); + } + + @Override + public AkkiBlizzardHerder copy() { + return new AkkiBlizzardHerder(this); + } +} diff --git a/Mage.Sets/src/mage/sets/betrayersofkamigawa/CrackTheEarth.java b/Mage.Sets/src/mage/sets/betrayersofkamigawa/CrackTheEarth.java new file mode 100644 index 0000000000..97bec7b9e5 --- /dev/null +++ b/Mage.Sets/src/mage/sets/betrayersofkamigawa/CrackTheEarth.java @@ -0,0 +1,62 @@ +/* + * 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 LIAB8LE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.betrayersofkamigawa; + +import java.util.UUID; + +import mage.Constants.CardType; +import mage.Constants.Rarity; +import mage.abilities.effects.common.SacrificeAllEffect; +import mage.cards.CardImpl; +import mage.filter.common.FilterControlledPermanent; + +/** + * + * @author LevelX + */ +public class CrackTheEarth extends CardImpl<CrackTheEarth> { + + public CrackTheEarth(UUID ownerId) { + super(ownerId, 98, "Crack the Earth", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{R}"); + this.expansionSetCode = "BOK"; + this.color.setRed(true); + // Each player sacrifices a permanent. + this.getSpellAbility().addEffect(new SacrificeAllEffect(1, new FilterControlledPermanent("permanent to sacrifice"))); + + } + + public CrackTheEarth(final CrackTheEarth card) { + super(card); + } + + @Override + public CrackTheEarth copy() { + return new CrackTheEarth(this); + } +} + diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/AuraOfDominion.java b/Mage.Sets/src/mage/sets/championsofkamigawa/AuraOfDominion.java index 011d1a6368..5ab81ab994 100644 --- a/Mage.Sets/src/mage/sets/championsofkamigawa/AuraOfDominion.java +++ b/Mage.Sets/src/mage/sets/championsofkamigawa/AuraOfDominion.java @@ -39,6 +39,8 @@ import mage.abilities.costs.common.TapTargetCost; import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.UntapEnchantedEffect; +import mage.abilities.effects.common.UntapTargetEffect; import mage.abilities.keyword.EnchantAbility; import mage.cards.CardImpl; import mage.filter.Filter; @@ -72,7 +74,7 @@ public class AuraOfDominion extends CardImpl<AuraOfDominion> { this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Constants.Outcome.Untap)); this.addAbility(new EnchantAbility(auraTarget.getTargetName())); - Ability ability = new SimpleActivatedAbility(Constants.Zone.BATTLEFIELD, new AuraOfDominionEffect(), new GenericManaCost(1)); + Ability ability = new SimpleActivatedAbility(Constants.Zone.BATTLEFIELD, new UntapEnchantedEffect(), new GenericManaCost(1)); ability.addCost(new TapTargetCost(new TargetControlledCreaturePermanent(1, 1, filter, false))); this.addAbility(ability); } @@ -86,34 +88,4 @@ public class AuraOfDominion extends CardImpl<AuraOfDominion> { return new AuraOfDominion(this); } -} - -class AuraOfDominionEffect extends OneShotEffect<AuraOfDominionEffect> { - AuraOfDominionEffect() { - super(Constants.Outcome.Untap); - staticText = "untap enchanted creature"; - } - - AuraOfDominionEffect(final AuraOfDominionEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent != null) { - Permanent attach = game.getPermanent(permanent.getAttachedTo()); - if (attach != null) { - attach.untap(game); - return true; - } - } - return false; - } - - @Override - public AuraOfDominionEffect copy() { - return new AuraOfDominionEffect(this); - } - -} +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/CommuneWithNature.java b/Mage.Sets/src/mage/sets/championsofkamigawa/CommuneWithNature.java new file mode 100644 index 0000000000..84767a3dbf --- /dev/null +++ b/Mage.Sets/src/mage/sets/championsofkamigawa/CommuneWithNature.java @@ -0,0 +1,71 @@ +/* + * Copyright 2011 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +package mage.sets.championsofkamigawa; + +import java.util.UUID; +import mage.Constants.CardType; +import mage.Constants.Rarity; +import mage.abilities.dynamicvalue.common.StaticValue; +import mage.abilities.effects.common.LookLibraryAndPickControllerEffect; +import mage.abilities.effects.common.LookLibraryControllerEffect; +import mage.cards.CardImpl; +import mage.filter.FilterCard; + +/** + * + * @author LevelX + */ +public class CommuneWithNature extends CardImpl<CommuneWithNature> { + + private final static FilterCard filter = new FilterCard("creature card"); + static { + filter.getCardType().add(CardType.CREATURE); + } + + + public CommuneWithNature (UUID ownerId) { + super(ownerId, 204, "Commune with Nature", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{G}"); + this.expansionSetCode = "CHK"; + this.color.setGreen(true); + + // Look at the top five cards of your library. You may reveal a creature card from among them and put it into your hand. Put the rest on the bottom of your library in any order. + this.getSpellAbility().addEffect(new LookLibraryAndPickControllerEffect(new StaticValue(5), false, new StaticValue(1), filter, false)); + } + + public CommuneWithNature (final CommuneWithNature card) { + super(card); + } + + @Override + public CommuneWithNature copy() { + return new CommuneWithNature(this); + } + +} + diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/HikariTwilightGuardian.java b/Mage.Sets/src/mage/sets/championsofkamigawa/HikariTwilightGuardian.java index f7132bb14e..23f8ec144a 100644 --- a/Mage.Sets/src/mage/sets/championsofkamigawa/HikariTwilightGuardian.java +++ b/Mage.Sets/src/mage/sets/championsofkamigawa/HikariTwilightGuardian.java @@ -41,9 +41,6 @@ import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.ReturnFromExileEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; -import mage.filter.Filter; -import mage.filter.FilterCard; -import mage.filter.FilterSpell; import mage.filter.common.FilterSpiritOrArcaneCard; import mage.game.Game; import mage.game.events.GameEvent; @@ -94,7 +91,7 @@ class HikariTwilightGuardianEffect extends OneShotEffect<HikariTwilightGuardianE public boolean apply(Game game, Ability source) { Permanent permanent = game.getPermanent(source.getSourceId()); if (permanent != null) { - if (permanent.moveToExile(source.getSourceId(), "Hikari, Twilight Guardian Exile", source.getId(), game)) { + if (permanent.moveToExile(source.getSourceId(), "Hikari, Twilight Guardian", source.getId(), game)) { //create delayed triggered ability HikariTwilightGuardianDelayedTriggeredAbility delayedAbility = new HikariTwilightGuardianDelayedTriggeredAbility(source.getSourceId()); delayedAbility.setSourceId(source.getSourceId()); diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/OtherworldlyJourney.java b/Mage.Sets/src/mage/sets/championsofkamigawa/OtherworldlyJourney.java new file mode 100644 index 0000000000..54f525ffa0 --- /dev/null +++ b/Mage.Sets/src/mage/sets/championsofkamigawa/OtherworldlyJourney.java @@ -0,0 +1,141 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +package mage.sets.championsofkamigawa; + +import java.util.UUID; + +import mage.Constants; +import mage.Constants.CardType; +import mage.Constants.Rarity; +import mage.abilities.Ability; +import mage.abilities.DelayedTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ReturnFromExileEffect; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.cards.CardImpl; +import mage.counters.CounterType; +import mage.game.ExileZone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.target.common.TargetCreaturePermanent; +import mage.target.targetpointer.FixedTarget; + +/** + * @author LevelX + */ +public class OtherworldlyJourney extends CardImpl<OtherworldlyJourney> { + + public OtherworldlyJourney(UUID ownerId) { + super(ownerId, 37, "Otherworldly Journey", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{1}{W}"); + this.expansionSetCode = "CHK"; + this.color.setWhite(true); + // Exile target creature. At the beginning of the next end step, return that card to the battlefield under its owner's control with a +1/+1 counter on it. + this.getSpellAbility().addEffect(new OtherworldlyJourneyEffect()); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + } + + public OtherworldlyJourney(final OtherworldlyJourney card) { + super(card); + } + + @Override + public OtherworldlyJourney copy() { + return new OtherworldlyJourney(this); + } + +} + +class OtherworldlyJourneyEffect extends OneShotEffect<OtherworldlyJourneyEffect> { + + private static final String effectText = "Exile target creature. At the beginning of the next end step, return that card to the battlefield under its owner's control with a +1/+1 counter on it"; + + OtherworldlyJourneyEffect ( ) { + super(Constants.Outcome.Benefit); + staticText = effectText; + } + + OtherworldlyJourneyEffect(OtherworldlyJourneyEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(source.getFirstTarget()); + if (permanent != null) { + if (permanent.moveToExile(source.getSourceId(), "Otherworldly Journey", source.getId(), game)) { + ExileZone exile = game.getExile().getExileZone(source.getSourceId()); + // only if permanent is in exile (tokens would be stop to exist) + if (exile != null && !exile.isEmpty()) { + //create delayed triggered ability + OtherworldlyJourneyDelayedTriggeredAbility delayedAbility = new OtherworldlyJourneyDelayedTriggeredAbility(source.getSourceId()); + delayedAbility.setSourceId(source.getSourceId()); + delayedAbility.setControllerId(source.getControllerId()); + AddCountersTargetEffect effect = new AddCountersTargetEffect(CounterType.P1P1.createInstance()); + effect.setTargetPointer(new FixedTarget(source.getFirstTarget())); + delayedAbility.addEffect(effect); + game.addDelayedTriggeredAbility(delayedAbility); + } + return true; + } + } + return false; + } + + @Override + public OtherworldlyJourneyEffect copy() { + return new OtherworldlyJourneyEffect(this); + } + +} + +class OtherworldlyJourneyDelayedTriggeredAbility extends DelayedTriggeredAbility<OtherworldlyJourneyDelayedTriggeredAbility> { + + OtherworldlyJourneyDelayedTriggeredAbility ( UUID exileId ) { + super(new ReturnFromExileEffect(exileId, Constants.Zone.BATTLEFIELD, "return that card to the battlefield under its owner's control with a +1/+1 counter on it")); + } + + OtherworldlyJourneyDelayedTriggeredAbility(OtherworldlyJourneyDelayedTriggeredAbility ability) { + super(ability); + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getType() == GameEvent.EventType.END_TURN_STEP_PRE) { + return true; + } + return false; + } + @Override + public OtherworldlyJourneyDelayedTriggeredAbility copy() { + return new OtherworldlyJourneyDelayedTriggeredAbility(this); + } + + +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/PeerThroughDepths.java b/Mage.Sets/src/mage/sets/championsofkamigawa/PeerThroughDepths.java new file mode 100644 index 0000000000..420b224add --- /dev/null +++ b/Mage.Sets/src/mage/sets/championsofkamigawa/PeerThroughDepths.java @@ -0,0 +1,75 @@ +/* + * Copyright 2011 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +package mage.sets.championsofkamigawa; + +import java.util.UUID; +import mage.Constants.CardType; +import mage.Constants.Rarity; +import mage.abilities.dynamicvalue.common.StaticValue; +import mage.abilities.effects.common.LookLibraryAndPickControllerEffect; +import mage.cards.CardImpl; +import mage.filter.Filter.ComparisonScope; +import mage.filter.FilterCard; + +/** + * + * @author LevelX + */ +public class PeerThroughDepths extends CardImpl<PeerThroughDepths> { + + private final static FilterCard filter = new FilterCard("instant or sorcery card"); + static { + filter.getCardType().add(CardType.SORCERY); + filter.getCardType().add(CardType.INSTANT); + filter.setNotScopeCardType(ComparisonScope.Any); + } + + + public PeerThroughDepths (UUID ownerId) { + super(ownerId, 78, "Peer Through Depths", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{1}{U}"); + this.expansionSetCode = "CHK"; + this.subtype.add("Arcane"); + this.color.setBlue(true); + + // Look at the top five cards of your library. You may reveal an instant or sorcery card from among them and put it into your hand. + // Put the rest on the bottom of your library in any order. + this.getSpellAbility().addEffect(new LookLibraryAndPickControllerEffect(new StaticValue(5), false, new StaticValue(1), filter, false)); + } + + public PeerThroughDepths (final PeerThroughDepths card) { + super(card); + } + + @Override + public PeerThroughDepths copy() { + return new PeerThroughDepths(this); + } + +} + diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/RagDealer.java b/Mage.Sets/src/mage/sets/championsofkamigawa/RagDealer.java new file mode 100644 index 0000000000..24c6321674 --- /dev/null +++ b/Mage.Sets/src/mage/sets/championsofkamigawa/RagDealer.java @@ -0,0 +1,156 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +package mage.sets.championsofkamigawa; + +import java.util.UUID; +import mage.Constants; +import mage.Constants.CardType; +import mage.Constants.Outcome; +import mage.Constants.Rarity; +import mage.Constants.Zone; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.BushidoAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.filter.FilterCard; +import mage.game.Game; +import mage.players.Player; +import mage.target.Target; +import mage.target.TargetCard; +import mage.target.TargetPlayer; +import mage.target.common.TargetCardInGraveyard; + +/** + * + * @author LevelX + */ +public class RagDealer extends CardImpl<RagDealer> { + + protected static final FilterCard filter = new FilterCard("up to three target cards from a single graveyard"); + + public RagDealer (UUID ownerId) { + super(ownerId, 138, "Rag Dealer", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{B}"); + this.expansionSetCode = "CHK"; + this.subtype.add("Human"); + this.subtype.add("Rogue"); + this.color.setBlack(true); + + this.power = new MageInt(1); + this.toughness = new MageInt(1); + // {2}{B}, {T}: Exile up to three target cards from a single graveyard. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new RagDealerExileEffect(), new ManaCostsImpl("{2}{B}")); + ability.addCost(new TapSourceCost()); + TargetPlayer target = new TargetPlayer(); + target.setTargetName("player from which graveyard you want to exile the cards"); + ability.addTarget(target); + ability.addTarget(new TargetCardInGraveyard(0,3,filter)); + this.addAbility(ability); + } + + public RagDealer (final RagDealer card) { + super(card); + } + + @Override + public RagDealer copy() { + return new RagDealer(this); + } + +} + +class RagDealerTargetCardsInGraveyard extends TargetCard<RagDealerTargetCardsInGraveyard> { + + public RagDealerTargetCardsInGraveyard(int minNumTargets, int maxNumTargets, FilterCard filter) { + super(minNumTargets, maxNumTargets, Constants.Zone.GRAVEYARD, filter); + this.targetName = "up to three target cards from a single graveyard"; + } + + public RagDealerTargetCardsInGraveyard(final RagDealerTargetCardsInGraveyard target) { + super(target); + } + + @Override + public boolean canTarget(UUID id, Ability source, Game game) { + Player player = game.getPlayer(source.getTargets().getFirstTarget()); + if (player != null) { + filter.getOwnerId().clear(); + filter.getOwnerId().add(player.getId()); + return super.canTarget(id, source, game); + } + return false; + } + + + @Override + public RagDealerTargetCardsInGraveyard copy() { + return new RagDealerTargetCardsInGraveyard(this); + } +} + +class RagDealerExileEffect extends OneShotEffect<RagDealerExileEffect> { + + public RagDealerExileEffect() { + super(Outcome.Exile); + } + + public RagDealerExileEffect(final RagDealerExileEffect effect) { + super(effect); + } + + @Override + public RagDealerExileEffect copy() { + return new RagDealerExileEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Target targetCards = source.getTargets().get(1); + if (targetCards != null) { + for (UUID targetID : targetCards.getTargets()) { + Card card = game.getCard(targetID); + if (card != null) { + card.moveToExile(null, "", source.getId(), game); + } + } + return true; + } + return false; + } + + @Override + public String getText(Mode mode) { + return "Exile " + mode.getTargets().get(1).getTargetName(); + } +} diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/Reciprocate.java b/Mage.Sets/src/mage/sets/championsofkamigawa/Reciprocate.java new file mode 100644 index 0000000000..8ac0cac613 --- /dev/null +++ b/Mage.Sets/src/mage/sets/championsofkamigawa/Reciprocate.java @@ -0,0 +1,130 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +package mage.sets.championsofkamigawa; + +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; + +import mage.Constants.CardType; +import mage.Constants.Rarity; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.effects.common.ExileTargetEffect; +import mage.cards.CardImpl; +import mage.filter.common.FilterCreaturePermanent; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; +import mage.target.common.TargetCreaturePermanent; +import mage.watchers.common.PlayerDamagedBySourceWatcher; + +/** + * @author LevelX + */ +public class Reciprocate extends CardImpl<Reciprocate> { + + public Reciprocate(UUID ownerId) { + super(ownerId, 40, "Reciprocate", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{1}{W}"); + this.expansionSetCode = "CHK"; + this.color.setWhite(true); + // Exile target creature that dealt damage to you this turn. + this.getSpellAbility().addEffect(new ExileTargetEffect()); + this.getSpellAbility().addTarget(new ReciprocateTarget()); + } + + public Reciprocate(final Reciprocate card) { + super(card); + } + + @Override + public Reciprocate copy() { + return new Reciprocate(this); + } + +} + +class ReciprocateTarget<T extends TargetCreaturePermanent<T>> extends TargetPermanent<TargetCreaturePermanent<T>> { + + public ReciprocateTarget() { + super(1, 1, new FilterCreaturePermanent(), false); + targetName = "creature that dealt damage to you this turn"; + } + + public ReciprocateTarget(final ReciprocateTarget target) { + super(target); + } + + @Override + public boolean canTarget(UUID id, Ability source, Game game) { + PlayerDamagedBySourceWatcher watcher = (PlayerDamagedBySourceWatcher) game.getState().getWatchers().get("PlayerDamagedBySource",source.getControllerId()); + if (watcher != null && watcher.damageSources.contains(id)) { + return super.canTarget(id, source, game); + } + return false; + } + + @Override + public Set<UUID> possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) { + Set<UUID> availablePossibleTargets = super.possibleTargets(sourceId, sourceControllerId, game); + Set<UUID> possibleTargets = new HashSet<UUID>(); + PlayerDamagedBySourceWatcher watcher = (PlayerDamagedBySourceWatcher) game.getState().getWatchers().get("PlayerDamagedBySource", sourceControllerId); + for (UUID targetId : availablePossibleTargets) { + Permanent permanent = game.getPermanent(targetId); + if(permanent != null && watcher != null && watcher.damageSources.contains(targetId)){ + possibleTargets.add(targetId); + } + } + return possibleTargets; + } + + @Override + public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) { + int remainingTargets = this.minNumberOfTargets - targets.size(); + if (remainingTargets == 0) + return true; + int count = 0; + MageObject targetSource = game.getObject(sourceId); + PlayerDamagedBySourceWatcher watcher = (PlayerDamagedBySourceWatcher) game.getState().getWatchers().get("PlayerDamagedBySource", sourceControllerId); + for (Permanent permanent: game.getBattlefield().getActivePermanents(filter, sourceControllerId, sourceId, game)) { + if (!targets.containsKey(permanent.getId()) && permanent.canBeTargetedBy(targetSource, sourceControllerId, game) + && watcher != null && watcher.damageSources.contains(permanent.getId())) { + count++; + if (count >= remainingTargets) + return true; + } + } + return false; + } + + @Override + public ReciprocateTarget copy() { + return new ReciprocateTarget(this); + } +} diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/WickedAkuba.java b/Mage.Sets/src/mage/sets/championsofkamigawa/WickedAkuba.java index d5f501fde9..00eef62397 100644 --- a/Mage.Sets/src/mage/sets/championsofkamigawa/WickedAkuba.java +++ b/Mage.Sets/src/mage/sets/championsofkamigawa/WickedAkuba.java @@ -33,16 +33,17 @@ import mage.Constants.CardType; import mage.Constants.Rarity; import mage.Constants.Zone; import mage.MageInt; +import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.ColoredManaCost; -//import mage.abilities.effects.common.continious.GainAbilitySourceEffect; import mage.abilities.effects.common.LoseLifeTargetEffect; import mage.cards.CardImpl; import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.game.stack.StackAbility; import mage.target.TargetPlayer; -import mage.target.common.TargetOpponent; -import mage.watchers.common.PlayerDamagedByWatcher; +import mage.watchers.common.PlayerDamagedBySourceWatcher; /** * @@ -63,8 +64,6 @@ public class WickedAkuba extends CardImpl<WickedAkuba> { Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new LoseLifeTargetEffect(1), new ColoredManaCost(Constants.ColoredManaSymbol.B)); ability.addTarget(new WickedAkubaTarget()); this.addAbility(ability); - // watcher to know if player was damaged by this Wicked Akuba - this.addWatcher(new PlayerDamagedByWatcher()); } public WickedAkuba(final WickedAkuba card) { @@ -78,7 +77,7 @@ public class WickedAkuba extends CardImpl<WickedAkuba> { } -class WickedAkubaTarget extends TargetPlayer<TargetOpponent> { +class WickedAkubaTarget extends TargetPlayer<WickedAkubaTarget> { public WickedAkubaTarget() { super(); @@ -92,30 +91,39 @@ class WickedAkubaTarget extends TargetPlayer<TargetOpponent> { @Override public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) { filter.getPlayerId().clear(); - PlayerDamagedByWatcher watcher = (PlayerDamagedByWatcher) game.getState().getWatchers().get("PlayerDamagedByWatcher", sourceId); - if (watcher != null) { - for (UUID playerId: game.getPlayer(sourceControllerId).getInRange()){ - if (watcher.damagedPlayers.contains(playerId)) - filter.getPlayerId().add(playerId); - } - if (filter.getPlayerId().isEmpty()) // neccessary because empty playerId filter allows all players - return false; + UUID source = null; + MageObject targetSource = game.getObject(sourceId); + if (targetSource instanceof StackAbility) { + StackAbility stackAbility = (StackAbility) targetSource; + source = stackAbility.getSourceId(); } + if (targetSource instanceof Permanent) { + Permanent permanent = (Permanent) targetSource; + source = permanent.getId(); + } + if (source != null) { + for (UUID playerId: game.getPlayer(sourceControllerId).getInRange()){ + PlayerDamagedBySourceWatcher watcher = (PlayerDamagedBySourceWatcher) game.getState().getWatchers().get("PlayerDamagedBySource", playerId); + if (watcher != null && watcher.damageSources.contains(source)) + filter.getPlayerId().add(playerId); + } + } + if (filter.getPlayerId().isEmpty()) // neccessary because empty playerId filter allows all players + return false; return super.canChoose(sourceId, sourceControllerId, game); } @Override public boolean canTarget(UUID id, Ability source, Game game) { filter.getPlayerId().clear(); - PlayerDamagedByWatcher watcher = (PlayerDamagedByWatcher) game.getState().getWatchers().get("PlayerDamagedByWatcher", source.getSourceId()); - if (watcher != null) { - for (UUID playerId: game.getPlayer(source.getControllerId()).getInRange()){ - if (watcher.damagedPlayers.contains(playerId)) - filter.getPlayerId().add(playerId); - } - if (filter.getPlayerId().isEmpty()) // neccessary because empty playerId filter allows all players - return false; - } + for (UUID playerId: game.getPlayer(source.getControllerId()).getInRange()){ + PlayerDamagedBySourceWatcher watcher = (PlayerDamagedBySourceWatcher) game.getState().getWatchers().get("PlayerDamagedBySource", playerId); + + if (watcher != null && watcher.damageSources.contains(source.getSourceId())) + filter.getPlayerId().add(playerId); + } + if (filter.getPlayerId().isEmpty()) // neccessary because empty playerId filter allows all players + return false; return super.canTarget(id, source, game); } diff --git a/Mage.Sets/src/mage/sets/conflux/FaerieMechanist.java b/Mage.Sets/src/mage/sets/conflux/FaerieMechanist.java new file mode 100644 index 0000000000..d75e01b8c9 --- /dev/null +++ b/Mage.Sets/src/mage/sets/conflux/FaerieMechanist.java @@ -0,0 +1,77 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +package mage.sets.conflux; + +import java.util.UUID; +import mage.Constants.CardType; +import mage.Constants.Rarity; +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.dynamicvalue.common.StaticValue; +import mage.abilities.effects.common.LookLibraryAndPickControllerEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.filter.FilterCard; + +/** + * + * @author LevelX + */ +public class FaerieMechanist extends CardImpl<FaerieMechanist> { + + private final static FilterCard filter = new FilterCard("artifact card"); + static { + filter.getCardType().add(CardType.ARTIFACT); + } + + public FaerieMechanist(UUID ownerId) { + super(ownerId, 27, "Faerie Mechanist", Rarity.COMMON, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{3}{U}"); + this.expansionSetCode = "CON"; + this.color.setBlue(true); + this.subtype.add("Faerie"); + this.subtype.add("Artificer"); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + // Flying + this.addAbility(FlyingAbility.getInstance()); + // When Faerie Mechanist enters the battlefield, look at the top three cards of your library. + // You may reveal an artifact card from among them and put it into your hand. Put the rest on the bottom of your library in any order. + this.addAbility(new EntersBattlefieldTriggeredAbility(new LookLibraryAndPickControllerEffect(new StaticValue(3), false, new StaticValue(1), filter, false))); + } + + public FaerieMechanist(final FaerieMechanist card) { + super(card); + } + + @Override + public FaerieMechanist copy() { + return new FaerieMechanist(this); + } + +} diff --git a/Mage.Sets/src/mage/sets/conflux/GiltspireAvenger.java b/Mage.Sets/src/mage/sets/conflux/GiltspireAvenger.java new file mode 100644 index 0000000000..e58dc70c94 --- /dev/null +++ b/Mage.Sets/src/mage/sets/conflux/GiltspireAvenger.java @@ -0,0 +1,149 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.conflux; + +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; +import mage.Constants.CardType; +import mage.Constants.Rarity; +import mage.Constants.Zone; +import mage.MageInt; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.keyword.ExaltedAbility; +import mage.cards.CardImpl; +import mage.filter.common.FilterCreaturePermanent; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; +import mage.target.common.TargetCreaturePermanent; +import mage.watchers.common.PlayerDamagedBySourceWatcher; + + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class GiltspireAvenger extends CardImpl<GiltspireAvenger> { + + public GiltspireAvenger(UUID ownerId) { + super(ownerId, 108, "Giltspire Avenger", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{G}{W}{U}"); + this.expansionSetCode = "CON"; + this.subtype.add("Human"); + this.subtype.add("Soldier"); + + this.color.setGreen(true); + this.color.setWhite(true); + this.color.setBlue(true); + + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Exalted (Whenever a creature you control attacks alone, that creature gets +1/+1 until end of turn.) + this.addAbility(new ExaltedAbility()); + + // {T}: Destroy target creature that dealt damage to you this turn. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DestroyTargetEffect(), new TapSourceCost()); + ability.addTarget(new GiltspireAvengerTarget()); + this.addAbility(ability); + + + } + + public GiltspireAvenger(final GiltspireAvenger card) { + super(card); + } + + @Override + public GiltspireAvenger copy() { + return new GiltspireAvenger(this); + } +} + +class GiltspireAvengerTarget<T extends TargetCreaturePermanent<T>> extends TargetPermanent<TargetCreaturePermanent<T>> { + + public GiltspireAvengerTarget() { + super(1, 1, new FilterCreaturePermanent(), false); + targetName = "creature that dealt damage to you this turn"; + } + + public GiltspireAvengerTarget(final GiltspireAvengerTarget target) { + super(target); + } + + @Override + public boolean canTarget(UUID id, Ability source, Game game) { + PlayerDamagedBySourceWatcher watcher = (PlayerDamagedBySourceWatcher) game.getState().getWatchers().get("PlayerDamagedBySource",source.getControllerId()); + if (watcher != null && watcher.damageSources.contains(id)) { + return super.canTarget(id, source, game); + } + return false; + } + + @Override + public Set<UUID> possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) { + Set<UUID> availablePossibleTargets = super.possibleTargets(sourceId, sourceControllerId, game); + Set<UUID> possibleTargets = new HashSet<UUID>(); + PlayerDamagedBySourceWatcher watcher = (PlayerDamagedBySourceWatcher) game.getState().getWatchers().get("PlayerDamagedBySource", sourceControllerId); + for (UUID targetId : availablePossibleTargets) { + Permanent permanent = game.getPermanent(targetId); + if(permanent != null && watcher != null && watcher.damageSources.contains(targetId)){ + possibleTargets.add(targetId); + } + } + return possibleTargets; + } + + @Override + public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) { + int remainingTargets = this.minNumberOfTargets - targets.size(); + if (remainingTargets == 0) + return true; + int count = 0; + MageObject targetSource = game.getObject(sourceId); + PlayerDamagedBySourceWatcher watcher = (PlayerDamagedBySourceWatcher) game.getState().getWatchers().get("PlayerDamagedBySource", sourceControllerId); + for (Permanent permanent: game.getBattlefield().getActivePermanents(filter, sourceControllerId, sourceId, game)) { + if (!targets.containsKey(permanent.getId()) && permanent.canBeTargetedBy(targetSource, sourceControllerId, game) + && watcher != null && watcher.damageSources.contains(permanent.getId())) { + count++; + if (count >= remainingTargets) + return true; + } + } + return false; + } + + @Override + public GiltspireAvengerTarget copy() { + return new GiltspireAvengerTarget(this); + } +} diff --git a/Mage.Sets/src/mage/sets/innistrad/Claustrophobia.java b/Mage.Sets/src/mage/sets/innistrad/Claustrophobia.java index 7869514483..1f1db3812c 100644 --- a/Mage.Sets/src/mage/sets/innistrad/Claustrophobia.java +++ b/Mage.Sets/src/mage/sets/innistrad/Claustrophobia.java @@ -29,21 +29,17 @@ package mage.sets.innistrad; import java.util.UUID; -import mage.Constants; import mage.Constants.CardType; import mage.Constants.Outcome; import mage.Constants.Rarity; import mage.Constants.Zone; -import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.AttachEffect; import mage.abilities.effects.common.SkipEnchantedUntapEffect; +import mage.abilities.effects.common.TapEnchantedEffect; import mage.abilities.keyword.EnchantAbility; import mage.cards.CardImpl; -import mage.game.Game; -import mage.game.permanent.Permanent; import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; @@ -65,7 +61,7 @@ public class Claustrophobia extends CardImpl<Claustrophobia> { this.getSpellAbility().addEffect(new AttachEffect(Outcome.Detriment)); this.addAbility(new EnchantAbility(auraTarget.getTargetName())); // When Claustrophobia enters the battlefield, tap enchanted creature. - this.addAbility(new EntersBattlefieldTriggeredAbility(new ClaustrophobiaEffect())); + this.addAbility(new EntersBattlefieldTriggeredAbility(new TapEnchantedEffect())); // Enchanted creature doesn't untap during its controller's untap step. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SkipEnchantedUntapEffect())); } @@ -79,31 +75,3 @@ public class Claustrophobia extends CardImpl<Claustrophobia> { return new Claustrophobia(this); } } - -class ClaustrophobiaEffect extends OneShotEffect<ClaustrophobiaEffect> { - ClaustrophobiaEffect() { - super(Constants.Outcome.Tap); - staticText = "tap enchanted creature"; - } - - ClaustrophobiaEffect(final ClaustrophobiaEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent enchantment = game.getPermanent(source.getSourceId()); - if (enchantment != null && enchantment.getAttachedTo() != null) { - Permanent permanent = game.getPermanent(enchantment.getAttachedTo()); - if (permanent != null) { - return permanent.tap(game); - } - } - return false; - } - - @Override - public ClaustrophobiaEffect copy() { - return new ClaustrophobiaEffect(); - } -} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/planarchaos/DuneriderOutlaw.java b/Mage.Sets/src/mage/sets/planarchaos/DuneriderOutlaw.java new file mode 100644 index 0000000000..2c4fa56bdc --- /dev/null +++ b/Mage.Sets/src/mage/sets/planarchaos/DuneriderOutlaw.java @@ -0,0 +1,86 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.planarchaos; + +import java.util.UUID; +import mage.Constants.CardType; +import mage.Constants.Rarity; +import mage.MageInt; +import mage.ObjectColor; +import mage.abilities.TriggeredAbility; +import mage.abilities.common.OnEventTriggeredAbility; +import mage.abilities.condition.common.DealtDamageToAnOpponent; +import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.keyword.ProtectionAbility; +import mage.cards.CardImpl; +import mage.counters.CounterType; +import mage.filter.FilterCard; +import mage.game.events.GameEvent; + +/** + * + * @author LevelX + */ +public class DuneriderOutlaw extends CardImpl<DuneriderOutlaw> { + + private static final String ruleText = "At the beginning of each end step, if {this} dealt damage to an opponent this turn, put a +1/+1 counter on it."; + private static final FilterCard filter = new FilterCard("green"); + + static { + filter.setColor(ObjectColor.GREEN); + filter.setUseColor(true); + } + + public DuneriderOutlaw(UUID ownerId) { + super(ownerId, 86, "Dunerider Outlaw", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{B}{B}"); + this.expansionSetCode = "PLC"; + this.subtype.add("Human"); + this.subtype.add("Rebel"); + this.subtype.add("Rogue"); + + this.color.setBlack(true); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Protection from green + this.addAbility(new ProtectionAbility(filter)); + // At the beginning of each end step, if Dunerider Outlaw dealt damage to an opponent this turn, put a +1/+1 counter on it. + TriggeredAbility triggered = new OnEventTriggeredAbility(GameEvent.EventType.END_TURN_STEP_PRE, "beginning of each end step", true, new AddCountersSourceEffect(CounterType.P1P1.createInstance())); + this.addAbility(new ConditionalTriggeredAbility(triggered, new DealtDamageToAnOpponent(), ruleText)); + } + + public DuneriderOutlaw(final DuneriderOutlaw card) { + super(card); + } + + @Override + public DuneriderOutlaw copy() { + return new DuneriderOutlaw(this); + } +} diff --git a/Mage.Sets/src/mage/sets/riseoftheeldrazi/AncientStirrings.java b/Mage.Sets/src/mage/sets/riseoftheeldrazi/AncientStirrings.java new file mode 100644 index 0000000000..1b623008db --- /dev/null +++ b/Mage.Sets/src/mage/sets/riseoftheeldrazi/AncientStirrings.java @@ -0,0 +1,72 @@ +/* + * Copyright 2011 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +package mage.sets.riseoftheeldrazi; + +import java.util.UUID; +import mage.Constants.CardType; +import mage.Constants.Rarity; +import mage.abilities.dynamicvalue.common.StaticValue; +import mage.abilities.effects.common.LookLibraryAndPickControllerEffect; +import mage.cards.CardImpl; +import mage.filter.FilterCard; + +/** + * + * @author LevelX + */ +public class AncientStirrings extends CardImpl<AncientStirrings> { + + private final static FilterCard filter = new FilterCard("colorless card"); + static { + filter.setColorless(true); + filter.setUseColorless(true); + } + + + public AncientStirrings (UUID ownerId) { + super(ownerId, 174, "Ancient Stirrings", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{G}"); + this.expansionSetCode = "ROE"; + this.color.setGreen(true); + + // Look at the top five cards of your library. You may reveal a colorless card from among them and put it into your hand. + // Then put the rest on the bottom of your library in any order. (Cards with no colored mana in their mana costs are colorless. Lands are also colorless.) + this.getSpellAbility().addEffect(new LookLibraryAndPickControllerEffect(new StaticValue(5), false, new StaticValue(1), filter, false)); + } + + public AncientStirrings (final AncientStirrings card) { + super(card); + } + + @Override + public AncientStirrings copy() { + return new AncientStirrings(this); + } + +} + diff --git a/Mage.Sets/src/mage/sets/riseoftheeldrazi/CrabUmbra.java b/Mage.Sets/src/mage/sets/riseoftheeldrazi/CrabUmbra.java index 979f0678b6..2da6584043 100644 --- a/Mage.Sets/src/mage/sets/riseoftheeldrazi/CrabUmbra.java +++ b/Mage.Sets/src/mage/sets/riseoftheeldrazi/CrabUmbra.java @@ -37,6 +37,7 @@ import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.UntapEnchantedEffect; import mage.abilities.keyword.EnchantAbility; import mage.abilities.keyword.TotemArmorAbility; import mage.cards.CardImpl; @@ -65,7 +66,7 @@ public class CrabUmbra extends CardImpl<CrabUmbra> { Ability ability = new EnchantAbility(auraTarget.getTargetName()); this.addAbility(ability); // {2}{U}: Untap enchanted creature. - this.addAbility(new SimpleActivatedAbility(Constants.Zone.BATTLEFIELD, new CrabUmbraEffect(), new ManaCostsImpl("{2}{U}"))); + this.addAbility(new SimpleActivatedAbility(Constants.Zone.BATTLEFIELD, new UntapEnchantedEffect(), new ManaCostsImpl("{2}{U}"))); this.addAbility(new TotemArmorAbility()); } @@ -77,34 +78,4 @@ public class CrabUmbra extends CardImpl<CrabUmbra> { public CrabUmbra copy() { return new CrabUmbra(this); } -} - -class CrabUmbraEffect extends OneShotEffect<CrabUmbraEffect> { - CrabUmbraEffect() { - super(Constants.Outcome.Untap); - staticText = "untap enchanted creature"; - } - - CrabUmbraEffect(final CrabUmbraEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent != null) { - Permanent attach = game.getPermanent(permanent.getAttachedTo()); - if (attach != null) { - attach.untap(game); - return true; - } - } - return false; - } - - @Override - public CrabUmbraEffect copy() { - return new CrabUmbraEffect(this); - } - -} +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/saviorsofkamigawa/DescendantOfSoramaro.java b/Mage.Sets/src/mage/sets/saviorsofkamigawa/DescendantOfSoramaro.java index 86f51ffbe9..f65a03c514 100644 --- a/Mage.Sets/src/mage/sets/saviorsofkamigawa/DescendantOfSoramaro.java +++ b/Mage.Sets/src/mage/sets/saviorsofkamigawa/DescendantOfSoramaro.java @@ -53,7 +53,7 @@ public class DescendantOfSoramaro extends CardImpl<DescendantOfSoramaro> { this.power = new MageInt(2); this.toughness = new MageInt(3); // {1}{U}: Look at the top X cards of your library, where X is the number of cards in your hand, then put them back in any order. - this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new LookLibraryControllerEffect(new CardsInControllerHandCount(), false), new ManaCostsImpl("{1}{U}"))); + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new LookLibraryControllerEffect(new CardsInControllerHandCount()), new ManaCostsImpl("{1}{U}"))); } public DescendantOfSoramaro(final DescendantOfSoramaro card) { diff --git a/Mage.Sets/src/mage/sets/saviorsofkamigawa/FreedFromTheReal.java b/Mage.Sets/src/mage/sets/saviorsofkamigawa/FreedFromTheReal.java new file mode 100644 index 0000000000..6871ca0a54 --- /dev/null +++ b/Mage.Sets/src/mage/sets/saviorsofkamigawa/FreedFromTheReal.java @@ -0,0 +1,77 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.saviorsofkamigawa; + +import java.util.UUID; + +import mage.Constants; +import mage.Constants.CardType; +import mage.Constants.Rarity; +import mage.Constants.Zone; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.TapEnchantedEffect; +import mage.abilities.effects.common.UntapEnchantedEffect; +import mage.abilities.keyword.EnchantAbility; +import mage.cards.CardImpl; +import mage.target.TargetPermanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LevelX + */ +public class FreedFromTheReal extends CardImpl<FreedFromTheReal> { + + public FreedFromTheReal(UUID ownerId) { + super(ownerId, 38, "Freed from the Real", Rarity.UNCOMMON, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}"); + this.expansionSetCode = "SOK"; + this.color.setBlue(true); + this.subtype.add("Aura"); + // Enchant creature + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Constants.Outcome.Untap)); + this.addAbility(new EnchantAbility(auraTarget.getTargetName())); + // {U}: Tap enchanted creature. + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new TapEnchantedEffect(), new ManaCostsImpl("{U}"))); + // {U}: Untap enchanted creature. + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new UntapEnchantedEffect(), new ManaCostsImpl("{U}"))); + + } + + public FreedFromTheReal(final FreedFromTheReal card) { + super(card); + } + + @Override + public FreedFromTheReal copy() { + return new FreedFromTheReal(this); + } +} diff --git a/Mage.Sets/src/mage/sets/timeshifted/WhirlingDervish.java b/Mage.Sets/src/mage/sets/timeshifted/WhirlingDervish.java new file mode 100644 index 0000000000..ce927364f0 --- /dev/null +++ b/Mage.Sets/src/mage/sets/timeshifted/WhirlingDervish.java @@ -0,0 +1,85 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.timeshifted; + +import java.util.UUID; +import mage.Constants.CardType; +import mage.Constants.Rarity; +import mage.MageInt; +import mage.ObjectColor; +import mage.abilities.TriggeredAbility; +import mage.abilities.common.OnEventTriggeredAbility; +import mage.abilities.condition.common.DealtDamageToAnOpponent; +import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.keyword.ProtectionAbility; +import mage.cards.CardImpl; +import mage.counters.CounterType; +import mage.filter.FilterCard; +import mage.game.events.GameEvent; + +/** + * + * @author LevelX + */ +public class WhirlingDervish extends CardImpl<WhirlingDervish> { + + private static final String ruleText = "At the beginning of each end step, if {this} dealt damage to an opponent this turn, put a +1/+1 counter on it."; + private static final FilterCard filter = new FilterCard("black"); + + static { + filter.setColor(ObjectColor.BLACK); + filter.setUseColor(true); + } + + public WhirlingDervish(UUID ownerId) { + super(ownerId, 90, "Whirling Dervish", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{G}{G}"); + this.expansionSetCode = "TSB"; + this.subtype.add("Human"); + this.subtype.add("Monk"); + + this.color.setGreen(true); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Protection from black + this.addAbility(new ProtectionAbility(filter)); + // At the beginning of each end step, if Whirling Dervish dealt damage to an opponent this turn, put a +1/+1 counter on it. + TriggeredAbility triggered = new OnEventTriggeredAbility(GameEvent.EventType.END_TURN_STEP_PRE, "beginning of each end step", true, new AddCountersSourceEffect(CounterType.P1P1.createInstance())); + this.addAbility(new ConditionalTriggeredAbility(triggered, new DealtDamageToAnOpponent(), ruleText)); + } + + public WhirlingDervish(final WhirlingDervish card) { + super(card); + } + + @Override + public WhirlingDervish copy() { + return new WhirlingDervish(this); + } +} diff --git a/Mage/src/mage/abilities/condition/common/DealtDamageToAnOpponent.java b/Mage/src/mage/abilities/condition/common/DealtDamageToAnOpponent.java new file mode 100644 index 0000000000..86c3ccd75d --- /dev/null +++ b/Mage/src/mage/abilities/condition/common/DealtDamageToAnOpponent.java @@ -0,0 +1,54 @@ +/* + * 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.abilities.condition.common; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.condition.Condition; +import mage.game.Game; +import mage.watchers.common.PlayerDamagedBySourceWatcher; + +/** + * @author LevelX + */ +public class DealtDamageToAnOpponent implements Condition { + + public DealtDamageToAnOpponent() { + } + + @Override + public boolean apply(Game game, Ability source) { + for (UUID opponentId: game.getOpponents(source.getControllerId())) { + PlayerDamagedBySourceWatcher watcher = (PlayerDamagedBySourceWatcher) game.getState().getWatchers().get("PlayerDamagedBySource", opponentId); + if (watcher != null && watcher.damageSources.contains(source.getSourceId())) + return true; + } + return false; + } +} + diff --git a/Mage/src/mage/abilities/effects/common/LookLibraryAndPickControllerEffect.java b/Mage/src/mage/abilities/effects/common/LookLibraryAndPickControllerEffect.java new file mode 100644 index 0000000000..c1ed9d8452 --- /dev/null +++ b/Mage/src/mage/abilities/effects/common/LookLibraryAndPickControllerEffect.java @@ -0,0 +1,125 @@ +/* + * + * 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.abilities.effects.common; + +import mage.Constants.Outcome; +import mage.Constants.Zone; +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.cards.Card; +import mage.cards.Cards; +import mage.cards.CardsImpl; +import mage.filter.FilterCard; +import mage.game.Game; +import mage.players.Player; +import mage.target.TargetCard; + +/** + * + * @author LevelX + */ +public class LookLibraryAndPickControllerEffect extends LookLibraryControllerEffect { + + protected FilterCard filter; // which kind of cards to reveal + protected DynamicValue numberToPick; + protected boolean revealPickedCards = true; + protected Zone targetPickedCards = Zone.HAND; // Hand, graveyard, library bottom, library top + protected int foundCardsToPick = 0; + + public LookLibraryAndPickControllerEffect(DynamicValue numberOfCards, boolean mayShuffleAfter, DynamicValue numberToPick, FilterCard pickFilter, boolean putOnTop) { + super(numberOfCards, mayShuffleAfter, putOnTop); + this.numberToPick = numberToPick; + this.filter = pickFilter; + } + + public LookLibraryAndPickControllerEffect(final LookLibraryAndPickControllerEffect effect) { + super(effect); + this.numberToPick = effect.numberToPick.clone(); + this.filter = effect.filter.copy(); + this.revealPickedCards = effect.revealPickedCards; + this.targetPickedCards = effect.targetPickedCards; + } + + @Override + public LookLibraryAndPickControllerEffect copy() { + return new LookLibraryAndPickControllerEffect(this); + + } + @Override + protected void cardLooked(Card card, Game game, Ability source) { + + if (numberToPick.calculate(game, source) > 0 && filter.match(card)) + ++foundCardsToPick; + } + + @Override + protected void actionWithSelectedCards(Cards cards, Game game, Ability source, String windowName) { + // You may reveal a creature card from among them and put it into your hand. + Player player = game.getPlayer(source.getControllerId()); + if (player != null && foundCardsToPick > 0 && player.chooseUse(Outcome.DrawCard, "Do you wish to reveal "+filter.getMessage()+" and put it into your hand?", game)) { + FilterCard pickFilter = filter.copy(); + pickFilter.setMessage(filter.getMessage()+" to reveal and put into your hand"); + TargetCard target = new TargetCard(Zone.PICK, pickFilter); + if (player.choose(Outcome.DrawCard, cards, target, game)) { + Card card = cards.get(target.getFirstTarget(), game); + if (card != null) { + cards.remove(card); + card.moveToZone(targetPickedCards, source.getId(), game, false); + if (revealPickedCards) { + Cards reveal = new CardsImpl(Zone.OUTSIDE); + reveal.add(card); + player.revealCards(windowName, reveal, game); + } + } + } + } + + } + + @Override + public String getText(Mode mode) { + StringBuilder sb = new StringBuilder(); + + if (numberToPick.calculate(null, null) > 0) { + sb.append(". You may reveal a "); + sb.append(filter.getMessage()).append(" from among them and put it into your ").append(targetPickedCards.toString().toLowerCase()); + sb.append(". Put the rest "); + if (putOnTop) + sb.append("back "); + else + sb.append("on the bottom of your library "); + sb.append("in any order"); + } + // get text frame from super class and inject action text + return setText(mode, sb.toString()); + } + +} diff --git a/Mage/src/mage/abilities/effects/common/LookLibraryControllerEffect.java b/Mage/src/mage/abilities/effects/common/LookLibraryControllerEffect.java index 5d59b2945c..72fd36a1dd 100644 --- a/Mage/src/mage/abilities/effects/common/LookLibraryControllerEffect.java +++ b/Mage/src/mage/abilities/effects/common/LookLibraryControllerEffect.java @@ -52,35 +52,43 @@ import mage.target.TargetCard; */ public class LookLibraryControllerEffect extends OneShotEffect<LookLibraryControllerEffect> { - private DynamicValue numberOfCards; - private boolean mayShuffleAfter; + protected DynamicValue numberOfCards; + protected boolean mayShuffleAfter = false; + protected boolean putOnTop = true; // if false on put back on bottom of library public LookLibraryControllerEffect() { this(1); } public LookLibraryControllerEffect(int numberOfCards) { - this(numberOfCards, false); + this(numberOfCards, false, true); } public LookLibraryControllerEffect(DynamicValue numberOfCards) { - this(numberOfCards, false); - } - - public LookLibraryControllerEffect(int numberOfCards, boolean mayShuffleAfter) { - this(new StaticValue(numberOfCards), mayShuffleAfter); + this(numberOfCards, false, true); } - public LookLibraryControllerEffect(DynamicValue numberOfCards, boolean mayShuffleAfter) { + public LookLibraryControllerEffect(int numberOfCards, boolean mayShuffleAfter) { + this(numberOfCards, mayShuffleAfter, true); + } + + public LookLibraryControllerEffect(int numberOfCards, boolean mayShuffleAfter, boolean putOnTop) { + this(new StaticValue(numberOfCards), mayShuffleAfter, putOnTop); + } + + public LookLibraryControllerEffect(DynamicValue numberOfCards, boolean mayShuffleAfter, boolean putOnTop) { super(Outcome.Benefit); this.numberOfCards = numberOfCards; this.mayShuffleAfter = mayShuffleAfter; - } + this.putOnTop = putOnTop; + } + public LookLibraryControllerEffect(final LookLibraryControllerEffect effect) { super(effect); this.numberOfCards = effect.numberOfCards.clone(); this.mayShuffleAfter = effect.mayShuffleAfter; + this.putOnTop = effect.putOnTop; } @Override @@ -92,6 +100,7 @@ public class LookLibraryControllerEffect extends OneShotEffect<LookLibraryContro @Override public boolean apply(Game game, Ability source) { String windowName ="Reveal"; + if (source instanceof SpellAbility) { Card sourceCard = game.getCard(source.getSourceId()); if (sourceCard != null) @@ -108,25 +117,58 @@ public class LookLibraryControllerEffect extends OneShotEffect<LookLibraryContro return false; } + // take cards from library and look at them Cards cards = new CardsImpl(Zone.PICK); int count = Math.min(player.getLibrary().size(), this.numberOfCards.calculate(game, source)); for (int i = 0; i < count; i++) { Card card = player.getLibrary().removeFromTop(game); if (card != null) { cards.add(card); + this.cardLooked(card, game, source); game.setZone(card.getId(), Zone.PICK); } } player.lookAtCards(windowName, cards, game); - TargetCard target = new TargetCard(Zone.PICK, new FilterCard("card to put on your library (last chosen will be on top)")); + this.actionWithSelectedCards(cards, game, source, windowName); + + this.putCardsBack(source, player, cards, game); + + this.mayShuffle(player, game); + + return true; + } + /** + * + * @param card + * @param game + * @param source + */ + protected void cardLooked(Card card, Game game, Ability source) { + return; + } + + protected void actionWithSelectedCards(Cards cards, Game game, Ability source, String windowName) { + return; + } + + /** + * Put the rest of the cards back to library + * + * @param source + * @param player + * @param cards + * @param game + */ + protected void putCardsBack(Ability source, Player player, Cards cards, Game game) { + TargetCard target = new TargetCard(Zone.PICK, new FilterCard(this.getPutBackText())); target.setRequired(true); while (cards.size() > 1) { player.choose(Outcome.Neutral, cards, target, game); Card card = cards.get(target.getFirstTarget(), game); if (card != null) { cards.remove(card); - card.moveToZone(Zone.LIBRARY, source.getId(), game, true); + card.moveToZone(Zone.LIBRARY, source.getId(), game, putOnTop); } target.clearChosen(); } @@ -134,19 +176,41 @@ public class LookLibraryControllerEffect extends OneShotEffect<LookLibraryContro Card card = cards.get(cards.iterator().next(), game); card.moveToZone(Zone.LIBRARY, source.getId(), game, true); } + } + + /** + * Check to shuffle library if allowed + * @param player + * @param game + */ + protected void mayShuffle(Player player, Game game) { if (this.mayShuffleAfter) { if (player.chooseUse(Constants.Outcome.Benefit, "Shuffle you library?", game)) { player.shuffleLibrary(game); } } - return true; + } + + protected String getPutBackText() { + StringBuilder sb = new StringBuilder("card to put "); + if (putOnTop) + sb.append("on your library (last chosen will be on top)"); + else + sb.append("on bottom of your library (last chosen will be on bottom)"); + return sb.toString(); } @Override public String getText(Mode mode) { - int number = numberOfCards.calculate(null, null); + return setText(mode, ""); + } + + + public String setText(Mode mode, String middleText) { + int numberLook = numberOfCards.calculate(null, null); +// int numberPick = numberToPick.calculate(null, null) ; StringBuilder sb = new StringBuilder("Look at the top "); - switch(number) { + switch(numberLook) { case 0: sb.append(" X "); break; @@ -166,20 +230,29 @@ public class LookLibraryControllerEffect extends OneShotEffect<LookLibraryContro sb.append("five"); break; default: - sb.append(number); + sb.append(numberLook); break; } - if (number != 1) + if (numberLook != 1) sb.append(" cards "); sb.append("of your Library"); - if (number == 0) + if (numberLook == 0) sb.append(", where {X} is the number of cards ").append(numberOfCards.getMessage()); - if (number > 1) - sb.append(", then put them back in any order"); + + + if (!middleText.isEmpty()) { + sb.append(middleText); + } + else { + if (numberLook > 1) + sb.append(", then put them back in any order"); + } if (this.mayShuffleAfter) sb.append(". You may shuffle your library"); + return sb.toString(); } + } diff --git a/Mage/src/mage/abilities/effects/common/ReturnFromExileEffect.java b/Mage/src/mage/abilities/effects/common/ReturnFromExileEffect.java index a95aae9e0f..385077f24b 100644 --- a/Mage/src/mage/abilities/effects/common/ReturnFromExileEffect.java +++ b/Mage/src/mage/abilities/effects/common/ReturnFromExileEffect.java @@ -51,12 +51,17 @@ public class ReturnFromExileEffect extends OneShotEffect<ReturnFromExileEffect> this(exileId, zone, false); } + public ReturnFromExileEffect(UUID exileId, Zone zone, String text) { + this(exileId, zone, false); + staticText = text; + } + public ReturnFromExileEffect(UUID exileId, Zone zone, boolean tapped) { super(Outcome.PutCardInPlay); this.exileId = exileId; this.zone = zone; this.tapped = tapped; - setText(); + setText(); } public ReturnFromExileEffect(final ReturnFromExileEffect effect) { diff --git a/Mage/src/mage/abilities/effects/common/SacrificeAllEffect.java b/Mage/src/mage/abilities/effects/common/SacrificeAllEffect.java index 2565568ef8..9b30471712 100644 --- a/Mage/src/mage/abilities/effects/common/SacrificeAllEffect.java +++ b/Mage/src/mage/abilities/effects/common/SacrificeAllEffect.java @@ -58,6 +58,7 @@ public class SacrificeAllEffect extends OneShotEffect<SacrificeAllEffect> { super(Outcome.Sacrifice); this.amount = amount; this.filter = filter; + setText(); } public SacrificeAllEffect(final SacrificeAllEffect effect) { diff --git a/Mage/src/mage/abilities/effects/common/TapEnchantedEffect.java b/Mage/src/mage/abilities/effects/common/TapEnchantedEffect.java new file mode 100644 index 0000000000..7285c1ee46 --- /dev/null +++ b/Mage/src/mage/abilities/effects/common/TapEnchantedEffect.java @@ -0,0 +1,70 @@ +/* +* 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.abilities.effects.common; + +import mage.Constants.Outcome; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * + * @author LevelX + */ +public class TapEnchantedEffect extends OneShotEffect<TapEnchantedEffect> { + + public TapEnchantedEffect() { + super(Outcome.Tap); + staticText = "tap enchanted creature"; + } + + public TapEnchantedEffect(final TapEnchantedEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(source.getSourceId()); + if (permanent != null) { + Permanent attach = game.getPermanent(permanent.getAttachedTo()); + if (attach != null) { + attach.tap(game); + return true; + } + } + return false; + } + + @Override + public TapEnchantedEffect copy() { + return new TapEnchantedEffect(this); + } + + } diff --git a/Mage/src/mage/abilities/effects/common/UntapEnchantedEffect.java b/Mage/src/mage/abilities/effects/common/UntapEnchantedEffect.java new file mode 100644 index 0000000000..aaaed63723 --- /dev/null +++ b/Mage/src/mage/abilities/effects/common/UntapEnchantedEffect.java @@ -0,0 +1,70 @@ +/* +* 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.abilities.effects.common; + +import mage.Constants.Outcome; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * + * @author LevelX + */ +public class UntapEnchantedEffect extends OneShotEffect<UntapEnchantedEffect> { + + public UntapEnchantedEffect() { + super(Outcome.Untap); + staticText = "untap enchanted creature"; + } + + public UntapEnchantedEffect(final UntapEnchantedEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(source.getSourceId()); + if (permanent != null) { + Permanent attach = game.getPermanent(permanent.getAttachedTo()); + if (attach != null) { + attach.untap(game); + return true; + } + } + return false; + } + + @Override + public UntapEnchantedEffect copy() { + return new UntapEnchantedEffect(this); + } + +} diff --git a/Mage/src/mage/game/GameImpl.java b/Mage/src/mage/game/GameImpl.java index 6be7c09078..930ac991c4 100644 --- a/Mage/src/mage/game/GameImpl.java +++ b/Mage/src/mage/game/GameImpl.java @@ -72,6 +72,7 @@ import org.apache.log4j.Logger; import java.io.IOException; import java.io.Serializable; import java.util.*; +import mage.watchers.common.PlayerDamagedBySourceWatcher; public abstract class GameImpl<T extends GameImpl<T>> implements Game, Serializable { @@ -490,8 +491,12 @@ public abstract class GameImpl<T extends GameImpl<T>> implements Game, Serializa saveState(); } - state.getWatchers().add(new MorbidWatcher()); - state.getWatchers().add(new CastSpellLastTurnWatcher()); + for (UUID playerId: state.getPlayerList(startingPlayerId)) { + state.getWatchers().add(new PlayerDamagedBySourceWatcher(playerId)); + } + state.getWatchers().add(new MorbidWatcher()); + state.getWatchers().add(new CastSpellLastTurnWatcher()); + //20100716 - 103.5 for (UUID playerId: state.getPlayerList(startingPlayerId)) { diff --git a/Mage/src/mage/watchers/common/PlayerDamagedByWatcher.java b/Mage/src/mage/watchers/common/PlayerDamagedBySourceWatcher.java similarity index 73% rename from Mage/src/mage/watchers/common/PlayerDamagedByWatcher.java rename to Mage/src/mage/watchers/common/PlayerDamagedBySourceWatcher.java index 2c97067561..90df3010ef 100644 --- a/Mage/src/mage/watchers/common/PlayerDamagedByWatcher.java +++ b/Mage/src/mage/watchers/common/PlayerDamagedBySourceWatcher.java @@ -37,32 +37,34 @@ import mage.game.events.GameEvent.EventType; import mage.watchers.WatcherImpl; /** - * + * Watcher stores whitch sources did damage to a player + * * @author LevelX */ -public class PlayerDamagedByWatcher extends WatcherImpl<PlayerDamagedByWatcher> { +public class PlayerDamagedBySourceWatcher extends WatcherImpl<PlayerDamagedBySourceWatcher> { - public List<UUID> damagedPlayers = new ArrayList<UUID>(); + public List<UUID> damageSources = new ArrayList<UUID>(); - public PlayerDamagedByWatcher() { - super("PlayerDamagedByWatcher", WatcherScope.CARD); + public PlayerDamagedBySourceWatcher(UUID playerId) { + super("PlayerDamagedBySource", WatcherScope.PLAYER); + setControllerId(playerId); } - public PlayerDamagedByWatcher(final PlayerDamagedByWatcher watcher) { + public PlayerDamagedBySourceWatcher(final PlayerDamagedBySourceWatcher watcher) { super(watcher); - this.damagedPlayers = watcher.damagedPlayers; + this.damageSources = watcher.damageSources; } @Override - public PlayerDamagedByWatcher copy() { - return new PlayerDamagedByWatcher(this); + public PlayerDamagedBySourceWatcher copy() { + return new PlayerDamagedBySourceWatcher(this); } @Override public void watch(GameEvent event, Game game) { if (event.getType() == EventType.DAMAGED_PLAYER) { - if (sourceId.equals(event.getSourceId()) && !damagedPlayers.contains(event.getTargetId())) { - damagedPlayers.add(event.getTargetId()); + if (event.getTargetId().equals(controllerId) && !damageSources.contains(event.getSourceId())) { + damageSources.add(event.getSourceId()); } } } @@ -70,6 +72,6 @@ public class PlayerDamagedByWatcher extends WatcherImpl<PlayerDamagedByWatcher> @Override public void reset() { super.reset(); - damagedPlayers.clear(); + damageSources.clear(); } }