diff --git a/Mage.Sets/src/mage/sets/alliances/ThoughtLash.java b/Mage.Sets/src/mage/sets/alliances/ThoughtLash.java new file mode 100644 index 0000000000..6f9c9f2720 --- /dev/null +++ b/Mage.Sets/src/mage/sets/alliances/ThoughtLash.java @@ -0,0 +1,52 @@ +/* + * 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.alliances; + +import java.util.UUID; + +/** + * + * @author emerald000 + */ +public class ThoughtLash extends mage.sets.masterseditionii.ThoughtLash { + + public ThoughtLash(UUID ownerId) { + super(ownerId); + this.cardNumber = 58; + this.expansionSetCode = "ALL"; + } + + public ThoughtLash(final ThoughtLash card) { + super(card); + } + + @Override + public ThoughtLash copy() { + return new ThoughtLash(this); + } +} diff --git a/Mage.Sets/src/mage/sets/commander2014/GiftOfEstates.java b/Mage.Sets/src/mage/sets/commander2014/GiftOfEstates.java index c87bb2c1f4..e4c6731a64 100644 --- a/Mage.Sets/src/mage/sets/commander2014/GiftOfEstates.java +++ b/Mage.Sets/src/mage/sets/commander2014/GiftOfEstates.java @@ -28,7 +28,7 @@ package mage.sets.commander2014; import java.util.UUID; -import mage.abilities.condition.common.OpponentControllsMoreCondition; +import mage.abilities.condition.common.OpponentControlsMoreCondition; import mage.abilities.decorator.ConditionalOneShotEffect; import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect; import mage.cards.CardImpl; @@ -60,7 +60,7 @@ public class GiftOfEstates extends CardImpl { // If an opponent controls more lands than you, search your library for up to three Plains cards, reveal them, and put them into your hand. Then shuffle your library. this.getSpellAbility().addEffect(new ConditionalOneShotEffect( new SearchLibraryPutInHandEffect(new TargetCardInLibrary(0, 3, filter), true), - new OpponentControllsMoreCondition(new FilterLandPermanent("lands")))); + new OpponentControlsMoreCondition(new FilterLandPermanent("lands")))); } public GiftOfEstates(final GiftOfEstates card) { diff --git a/Mage.Sets/src/mage/sets/legends/LandTax.java b/Mage.Sets/src/mage/sets/legends/LandTax.java index ffd80349b0..823758648d 100644 --- a/Mage.Sets/src/mage/sets/legends/LandTax.java +++ b/Mage.Sets/src/mage/sets/legends/LandTax.java @@ -29,7 +29,7 @@ package mage.sets.legends; import java.util.UUID; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; -import mage.abilities.condition.common.OpponentControllsMoreCondition; +import mage.abilities.condition.common.OpponentControlsMoreCondition; import mage.abilities.decorator.ConditionalTriggeredAbility; import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect; import mage.cards.CardImpl; @@ -53,7 +53,7 @@ public class LandTax extends CardImpl { // At the beginning of your upkeep, if an opponent controls more lands than you, you may search your library for up to three basic land cards, reveal them, and put them into your hand. If you do, shuffle your library. this.addAbility(new ConditionalTriggeredAbility( new BeginningOfUpkeepTriggeredAbility(new SearchLibraryPutInHandEffect(new TargetCardInLibrary(0, 3, new FilterBasicLandCard()), true), TargetController.YOU, true), - new OpponentControllsMoreCondition(new FilterLandPermanent("lands")), + new OpponentControlsMoreCondition(new FilterLandPermanent("lands")), "At the beginning of your upkeep, if an opponent controls more lands than you, you may search your library for up to three basic land cards, reveal them, and put them into your hand. If you do, shuffle your library" )); diff --git a/Mage.Sets/src/mage/sets/masterseditionii/ThoughtLash.java b/Mage.Sets/src/mage/sets/masterseditionii/ThoughtLash.java new file mode 100644 index 0000000000..e8a28e8196 --- /dev/null +++ b/Mage.Sets/src/mage/sets/masterseditionii/ThoughtLash.java @@ -0,0 +1,182 @@ +/* + * 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.masterseditionii; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.ExileFromTopOfLibraryCost; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.PreventionEffectImpl; +import mage.abilities.keyword.CumulativeUpkeepAbility; +import mage.cards.CardImpl; +import mage.cards.Cards; +import mage.cards.CardsImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; +import mage.players.Player; + +/** + * + * @author emerald000 + */ +public class ThoughtLash extends CardImpl { + + public ThoughtLash(UUID ownerId) { + super(ownerId, 70, "Thought Lash", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}{U}"); + this.expansionSetCode = "ME2"; + + // Cumulative upkeep - Exile the top card of your library. + this.addAbility(new CumulativeUpkeepAbility(new ExileFromTopOfLibraryCost(1))); + + // When a player doesn't pay Thought Lash's cumulative upkeep, that player exiles all cards from his or her library. + this.addAbility(new ThoughtLashTriggeredAbility()); + + // Exile the top card of your library: Prevent the next 1 damage that would be dealt to you this turn. + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new ThoughtLashPreventionEffect(), new ExileFromTopOfLibraryCost(1))); + } + + public ThoughtLash(final ThoughtLash card) { + super(card); + } + + @Override + public ThoughtLash copy() { + return new ThoughtLash(this); + } +} + +class ThoughtLashTriggeredAbility extends TriggeredAbilityImpl { + + ThoughtLashTriggeredAbility() { + super(Zone.BATTLEFIELD, new ThoughtLashExileLibraryEffect(), false); + } + + ThoughtLashTriggeredAbility(final ThoughtLashTriggeredAbility ability) { + super(ability); + } + + @Override + public ThoughtLashTriggeredAbility copy() { + return new ThoughtLashTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == EventType.DIDNT_PAY_CUMULATIVE_UPKEEP; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + return event.getSourceId() == this.getSourceId(); + } + + @Override + public String getRule() { + return "When a player doesn't pay {this}'s cumulative upkeep, that player exiles all cards from his or her library."; + } +} + +class ThoughtLashExileLibraryEffect extends OneShotEffect { + + ThoughtLashExileLibraryEffect() { + super(Outcome.Detriment); + this.staticText = "that player exiles all cards from his or her library"; + } + + ThoughtLashExileLibraryEffect(final ThoughtLashExileLibraryEffect effect) { + super(effect); + } + + @Override + public ThoughtLashExileLibraryEffect copy() { + return new ThoughtLashExileLibraryEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + Cards cards = new CardsImpl(); + cards.addAll(controller.getLibrary().getTopCards(game, controller.getLibrary().size())); + controller.moveCards(cards, Zone.LIBRARY, Zone.EXILED, source, game); + return true; + } + return false; + } +} + +class ThoughtLashPreventionEffect extends PreventionEffectImpl { + + ThoughtLashPreventionEffect() { + super(Duration.EndOfTurn); + this.staticText = "Prevent the next 1 damage that would be dealt to you this turn"; + } + + ThoughtLashPreventionEffect(final ThoughtLashPreventionEffect effect) { + super(effect); + } + + @Override + public ThoughtLashPreventionEffect copy() { + return new ThoughtLashPreventionEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + GameEvent preventEvent = new GameEvent(GameEvent.EventType.PREVENT_DAMAGE, + source.getControllerId(), source.getSourceId(), source.getControllerId(), event.getAmount(), false); + if (!game.replaceEvent(preventEvent)) { + int damage = event.getAmount(); + if (damage > 0) { + event.setAmount(damage - 1); + this.used = true; + game.fireEvent(GameEvent.getEvent(GameEvent.EventType.PREVENTED_DAMAGE, + source.getControllerId(), source.getSourceId(), source.getControllerId(), 1)); + } + } + return false; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + return !this.used && super.applies(event, source, game) && event.getTargetId().equals(source.getControllerId()); + } +} diff --git a/Mage.Sets/src/mage/sets/mirrodin/SpellweaverHelix.java b/Mage.Sets/src/mage/sets/mirrodin/SpellweaverHelix.java new file mode 100644 index 0000000000..e83b0afe79 --- /dev/null +++ b/Mage.Sets/src/mage/sets/mirrodin/SpellweaverHelix.java @@ -0,0 +1,231 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.mirrodin; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.game.stack.Spell; +import mage.players.Player; +import mage.target.common.TargetCardInASingleGraveyard; +import mage.target.targetpointer.FixedTarget; +import mage.util.CardUtil; + +/** + * + * @author emerald000 + */ +public class SpellweaverHelix extends CardImpl { + + private static final FilterCard filter = new FilterCard("sorcery cards from a single graveyard"); + static { + filter.add(new CardTypePredicate(CardType.SORCERY)); + } + + public SpellweaverHelix(UUID ownerId) { + super(ownerId, 247, "Spellweaver Helix", Rarity.RARE, new CardType[]{CardType.ARTIFACT}, "{3}"); + this.expansionSetCode = "MRD"; + + // Imprint - When Spellweaver Helix enters the battlefield, you may exile two target sorcery cards from a single graveyard. + Ability ability = new EntersBattlefieldTriggeredAbility(new SpellweaverHelixImprintEffect(), true, "Imprint — "); + ability.addTarget(new TargetCardInASingleGraveyard(2, 2, filter)); + this.addAbility(ability); + + // Whenever a player casts a card, if it has the same name as one of the cards exiled with Spellweaver Helix, you may copy the other. If you do, you may cast the copy without paying its mana cost. + this.addAbility(new SpellweaverHelixTriggeredAbility()); + } + + public SpellweaverHelix(final SpellweaverHelix card) { + super(card); + } + + @java.lang.Override + public SpellweaverHelix copy() { + return new SpellweaverHelix(this); + } +} + +class SpellweaverHelixImprintEffect extends OneShotEffect { + + SpellweaverHelixImprintEffect() { + super(Outcome.Exile); + this.staticText = "you may exile two target sorcery cards from a single graveyard"; + } + + SpellweaverHelixImprintEffect(final SpellweaverHelixImprintEffect effect) { + super(effect); + } + + @java.lang.Override + public SpellweaverHelixImprintEffect copy() { + return new SpellweaverHelixImprintEffect(this); + } + + @java.lang.Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + Permanent sourcePermanent = game.getPermanent(source.getSourceId()); + for (UUID targetId : this.getTargetPointer().getTargets(game, source)) { + Card card = game.getCard(targetId); + if (card != null) { + controller.moveCardsToExile(card, source, game, true, CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter()), source.getSourceObject(game).getIdName()); + if (sourcePermanent != null) { + sourcePermanent.imprint(targetId, game); + } + } + } + return true; + } + return false; + } +} + +class SpellweaverHelixTriggeredAbility extends TriggeredAbilityImpl { + + SpellweaverHelixTriggeredAbility() { + super(Zone.BATTLEFIELD, new SpellweaverHelixCastEffect(), false); + } + + SpellweaverHelixTriggeredAbility(final SpellweaverHelixTriggeredAbility ability) { + super(ability); + } + + @java.lang.Override + public SpellweaverHelixTriggeredAbility copy() { + return new SpellweaverHelixTriggeredAbility(this); + } + + @java.lang.Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.SPELL_CAST; + } + + @java.lang.Override + public boolean checkTrigger(GameEvent event, Game game) { + Spell spell = game.getStack().getSpell(event.getTargetId()); + if (spell != null && spell.getCard() != null && !spell.getCard().isCopy()) { + for (Effect effect : this.getEffects()) { + effect.setTargetPointer(new FixedTarget(spell.getId())); + } + return true; + } + return false; + } + + @java.lang.Override + public boolean checkInterveningIfClause(Game game) { + Spell spell = game.getStack().getSpell(this.getEffects().get(0).getTargetPointer().getFirst(game, this)); + if (spell != null) { + String spellName = spell.getName(); + Permanent sourcePermanent = game.getPermanent(this.getSourceId()); + if (sourcePermanent != null) { + for (UUID imprintId : sourcePermanent.getImprinted()) { + Card card = game.getCard(imprintId); + if (card != null && card.getName().equals(spellName)) { + ((SpellweaverHelixCastEffect) this.getEffects().get(0)).setSpellName(spellName); + return true; + } + } + } + } + return false; + } + + @java.lang.Override + public String getRule() { + return "Whenever a player casts a card, if it has the same name as one of the cards exiled with Spellweaver Helix, you may copy the other. If you do, you may cast the copy without paying its mana cost."; + } +} + +class SpellweaverHelixCastEffect extends OneShotEffect { + + private String spellName = ""; + + SpellweaverHelixCastEffect() { + super(Outcome.Benefit); + this.staticText = "you may copy the other. If you do, you may cast the copy without paying its mana cost"; + } + + SpellweaverHelixCastEffect(final SpellweaverHelixCastEffect effect) { + super(effect); + this.spellName = effect.spellName; + } + + @java.lang.Override + public SpellweaverHelixCastEffect copy() { + return new SpellweaverHelixCastEffect(this); + } + + public void setSpellName(String spellName) { + this.spellName = spellName; + } + + @java.lang.Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId()); + if (sourcePermanent != null) { + boolean foundSpellWithSameName = false; + for (UUID imprintId : sourcePermanent.getImprinted()) { + Card card = game.getCard(imprintId); + if (card != null) { + if (!foundSpellWithSameName && card.getName().equals(spellName)) { + foundSpellWithSameName = true; + } + else { + if (controller.chooseUse(Outcome.Copy, "Copy " + card.getIdName(), source, game)) { + Card copy = game.copyCard(card, source, source.getControllerId()); + if (controller.chooseUse(Outcome.PlayForFree, "Cast " + copy.getIdName() + " without paying its mana cost?", source, game)) { + controller.cast(copy.getSpellAbility(), game, true); + } + } + } + } + } + } + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/onslaught/WeatheredWayfarer.java b/Mage.Sets/src/mage/sets/onslaught/WeatheredWayfarer.java index 74c9474f8e..738cd6a0d1 100644 --- a/Mage.Sets/src/mage/sets/onslaught/WeatheredWayfarer.java +++ b/Mage.Sets/src/mage/sets/onslaught/WeatheredWayfarer.java @@ -35,7 +35,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.condition.Condition; -import mage.abilities.condition.common.OpponentControllsMoreCondition; +import mage.abilities.condition.common.OpponentControlsMoreCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect; @@ -67,7 +67,7 @@ public class WeatheredWayfarer extends CardImpl { Zone.BATTLEFIELD, new SearchLibraryPutInHandEffect(new TargetCardInLibrary(new FilterLandCard()), true, true), new ManaCostsImpl("{W}"), - new OpponentControllsMoreCondition(new FilterLandPermanent("lands"))); + new OpponentControlsMoreCondition(new FilterLandPermanent("lands"))); ability.addCost(new TapSourceCost()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/sets/ravnica/ConcertedEffort.java b/Mage.Sets/src/mage/sets/ravnica/ConcertedEffort.java new file mode 100644 index 0000000000..672cfe903e --- /dev/null +++ b/Mage.Sets/src/mage/sets/ravnica/ConcertedEffort.java @@ -0,0 +1,164 @@ +/* + * 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.ravnica; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.GainAbilityAllEffect; +import mage.abilities.keyword.DoubleStrikeAbility; +import mage.abilities.keyword.FearAbility; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.LandwalkAbility; +import mage.abilities.keyword.ProtectionAbility; +import mage.abilities.keyword.TrampleAbility; +import mage.abilities.keyword.VigilanceAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * + * @author emerald000 + */ +public class ConcertedEffort extends CardImpl { + + public ConcertedEffort(UUID ownerId) { + super(ownerId, 8, "Concerted Effort", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}{W}"); + this.expansionSetCode = "RAV"; + + // At the beginning of each upkeep, creatures you control gain flying until end of turn if a creature you control has flying. The same is true for fear, first strike, double strike, landwalk, protection, trample, and vigilance. + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new ConcertedEffortEffect(), TargetController.ANY, false)); + } + + public ConcertedEffort(final ConcertedEffort card) { + super(card); + } + + @Override + public ConcertedEffort copy() { + return new ConcertedEffort(this); + } +} + +class ConcertedEffortEffect extends OneShotEffect { + + private static final FilterCreaturePermanent filterFlying = new FilterCreaturePermanent(); + private static final FilterCreaturePermanent filterFear = new FilterCreaturePermanent(); + private static final FilterCreaturePermanent filterFirstStrike = new FilterCreaturePermanent(); + private static final FilterCreaturePermanent filterDoubleStrike = new FilterCreaturePermanent(); + private static final FilterCreaturePermanent filterLandwalk = new FilterCreaturePermanent(); + private static final FilterCreaturePermanent filterProtection = new FilterCreaturePermanent(); + private static final FilterCreaturePermanent filterTrample = new FilterCreaturePermanent(); + private static final FilterCreaturePermanent filterVigilance = new FilterCreaturePermanent(); + static { + filterFlying.add(new AbilityPredicate(FlyingAbility.class)); + filterFear.add(new AbilityPredicate(FearAbility.class)); + filterFirstStrike.add(new AbilityPredicate(FirstStrikeAbility.class)); + filterDoubleStrike.add(new AbilityPredicate(DoubleStrikeAbility.class)); + filterLandwalk.add(new AbilityPredicate(LandwalkAbility.class)); + filterProtection.add(new AbilityPredicate(ProtectionAbility.class)); + filterTrample.add(new AbilityPredicate(TrampleAbility.class)); + filterVigilance.add(new AbilityPredicate(VigilanceAbility.class)); + } + + ConcertedEffortEffect() { + super(Outcome.BoostCreature); + this.staticText = "creatures you control gain flying until end of turn if a creature you control has flying. The same is true for fear, first strike, double strike, landwalk, protection, trample, and vigilance"; + } + + ConcertedEffortEffect(final ConcertedEffortEffect effect) { + super(effect); + } + + @Override + public ConcertedEffortEffect copy() { + return new ConcertedEffortEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + // Flying + if (game.getBattlefield().contains(filterFlying, source.getControllerId(), 1, game)) { + game.addEffect(new GainAbilityAllEffect(FlyingAbility.getInstance(), Duration.EndOfTurn), source); + } + + // Fear + if (game.getBattlefield().contains(filterFear, source.getControllerId(), 1, game)) { + game.addEffect(new GainAbilityAllEffect(FearAbility.getInstance(), Duration.EndOfTurn), source); + } + + // First strike + if (game.getBattlefield().contains(filterFirstStrike, source.getControllerId(), 1, game)) { + game.addEffect(new GainAbilityAllEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn), source); + } + + // Double strike + if (game.getBattlefield().contains(filterDoubleStrike, source.getControllerId(), 1, game)) { + game.addEffect(new GainAbilityAllEffect(DoubleStrikeAbility.getInstance(), Duration.EndOfTurn), source); + } + + // Landwalk + for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filterLandwalk, source.getControllerId(), game)) { + for (Ability ability : permanent.getAbilities(game)) { + if (ability instanceof LandwalkAbility) { + game.addEffect(new GainAbilityAllEffect(ability, Duration.EndOfTurn), source); + } + } + } + + // Protection + for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filterProtection, source.getControllerId(), game)) { + for (Ability ability : permanent.getAbilities(game)) { + if (ability instanceof ProtectionAbility) { + game.addEffect(new GainAbilityAllEffect(ability, Duration.EndOfTurn), source); + } + } + } + + // Trample + if (game.getBattlefield().contains(filterTrample, source.getControllerId(), 1, game)) { + game.addEffect(new GainAbilityAllEffect(TrampleAbility.getInstance(), Duration.EndOfTurn), source); + } + + // Vigilance + if (game.getBattlefield().contains(filterVigilance, source.getControllerId(), 1, game)) { + game.addEffect(new GainAbilityAllEffect(VigilanceAbility.getInstance(), Duration.EndOfTurn), source); + } + return true; + } +} diff --git a/Mage.Sets/src/mage/sets/shardsofalara/KnightOfTheWhiteOrchid.java b/Mage.Sets/src/mage/sets/shardsofalara/KnightOfTheWhiteOrchid.java index 92a3e4ead3..7cd19df83b 100644 --- a/Mage.Sets/src/mage/sets/shardsofalara/KnightOfTheWhiteOrchid.java +++ b/Mage.Sets/src/mage/sets/shardsofalara/KnightOfTheWhiteOrchid.java @@ -33,7 +33,7 @@ import mage.constants.CardType; import mage.constants.Rarity; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.condition.common.OpponentControllsMoreCondition; +import mage.abilities.condition.common.OpponentControlsMoreCondition; import mage.abilities.decorator.ConditionalTriggeredAbility; import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect; import mage.abilities.keyword.FirstStrikeAbility; @@ -63,7 +63,7 @@ public class KnightOfTheWhiteOrchid extends CardImpl { // When Knight of the White Orchid enters the battlefield, if an opponent controls more lands than you, you may search your library for a Plains card, put it onto the battlefield, then shuffle your library. this.addAbility(new ConditionalTriggeredAbility( new EntersBattlefieldTriggeredAbility(new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(0, 1, new FilterBySubtypeCard("Plains")), false), true), - new OpponentControllsMoreCondition(new FilterLandPermanent("lands")), + new OpponentControlsMoreCondition(new FilterLandPermanent("lands")), "When {this} enters the battlefield, if an opponent controls more lands than you, you may search your library for a Plains card, put it onto the battlefield, then shuffle your library")); } diff --git a/Mage.Sets/src/mage/sets/torment/ChainerDementiaMaster.java b/Mage.Sets/src/mage/sets/torment/ChainerDementiaMaster.java new file mode 100644 index 0000000000..88929b04b2 --- /dev/null +++ b/Mage.Sets/src/mage/sets/torment/ChainerDementiaMaster.java @@ -0,0 +1,144 @@ +/* + * 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.torment; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.UUID; +import mage.MageInt; +import mage.ObjectColor; +import mage.abilities.Ability; +import mage.abilities.common.LeavesBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.common.PayLifeCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ExileAllEffect; +import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect; +import mage.abilities.effects.common.continuous.BecomesColorTargetEffect; +import mage.abilities.effects.common.continuous.BecomesSubtypeTargetEffect; +import mage.abilities.effects.common.continuous.BoostAllEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterCreatureCard; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetCardInGraveyard; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author emerald000 + */ +public class ChainerDementiaMaster extends CardImpl { + + private static final FilterCreaturePermanent filterCreature = new FilterCreaturePermanent("Nightmare creatures"); + private static final FilterPermanent filterPermanent = new FilterPermanent("Nightmares"); + static { + filterCreature.add(new SubtypePredicate("Nightmare")); + filterPermanent.add(new SubtypePredicate("Nightmare")); + } + + public ChainerDementiaMaster(UUID ownerId) { + super(ownerId, 56, "Chainer, Dementia Master", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{3}{B}{B}"); + this.expansionSetCode = "TOR"; + this.supertype.add("Legendary"); + this.subtype.add("Human"); + this.subtype.add("Minion"); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Nightmare creatures get +1/+1. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostAllEffect(1, 1, Duration.WhileOnBattlefield, filterCreature, false))); + + // {B}{B}{B}, Pay 3 life: Put target creature card from a graveyard onto the battlefield under your control. That creature is black and is a Nightmare in addition to its other creature types. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ChainerDementiaMasterEffect(), new ManaCostsImpl<>("{B}{B}{B}")); + ability.addCost(new PayLifeCost(3)); + ability.addTarget(new TargetCardInGraveyard(new FilterCreatureCard("creature card from a graveyard"))); + this.addAbility(ability); + + // When Chainer, Dementia Master leaves the battlefield, exile all Nightmares. + this.addAbility(new LeavesBattlefieldTriggeredAbility(new ExileAllEffect(filterPermanent), false)); + } + + public ChainerDementiaMaster(final ChainerDementiaMaster card) { + super(card); + } + + @Override + public ChainerDementiaMaster copy() { + return new ChainerDementiaMaster(this); + } +} + +class ChainerDementiaMasterEffect extends OneShotEffect { + + ChainerDementiaMasterEffect() { + super(Outcome.PutCreatureInPlay); + this.staticText = "Put target creature card from a graveyard onto the battlefield under your control. That creature is black and is a Nightmare in addition to its other creature types"; + } + + ChainerDementiaMasterEffect(final ChainerDementiaMasterEffect effect) { + super(effect); + } + + @Override + public ChainerDementiaMasterEffect copy() { + return new ChainerDementiaMasterEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + UUID cardId = this.getTargetPointer().getFirst(game, source); + new ReturnFromGraveyardToBattlefieldTargetEffect().apply(game, source); + Permanent permanent = game.getPermanent(cardId); + if (permanent != null) { + ContinuousEffectImpl effect = new BecomesColorTargetEffect(ObjectColor.BLACK, Duration.WhileOnBattlefield); + effect.setTargetPointer(new FixedTarget(permanent, game)); + game.addEffect(effect, source); + effect = new BecomesSubtypeTargetEffect(Duration.WhileOnBattlefield, new ArrayList<>(Arrays.asList("Nightmare")), false); + effect.setTargetPointer(new FixedTarget(permanent, game)); + game.addEffect(effect, source); + } + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/visions/Tithe.java b/Mage.Sets/src/mage/sets/visions/Tithe.java new file mode 100644 index 0000000000..dd0563cc51 --- /dev/null +++ b/Mage.Sets/src/mage/sets/visions/Tithe.java @@ -0,0 +1,98 @@ +/* + * 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.visions; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.filter.FilterCard; +import mage.filter.common.FilterLandPermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.game.Game; +import mage.target.common.TargetCardInLibrary; +import mage.target.common.TargetOpponent; + +/** + * + * @author emerald000 + */ +public class Tithe extends CardImpl { + + public Tithe(UUID ownerId) { + super(ownerId, 84, "Tithe", Rarity.RARE, new CardType[]{CardType.INSTANT}, "{W}"); + this.expansionSetCode = "VIS"; + + // Search your library for a Plains card. If target opponent controls more lands than you, you may search your library for an additional Plains card. Reveal those cards and put them into your hand. Then shuffle your library. + this.getSpellAbility().addEffect(new TitheEffect()); + this.getSpellAbility().addTarget(new TargetOpponent()); + } + + public Tithe(final Tithe card) { + super(card); + } + + @Override + public Tithe copy() { + return new Tithe(this); + } +} + +class TitheEffect extends OneShotEffect { + + private static final FilterCard filter = new FilterCard("Plains"); + static { + filter.add(new SubtypePredicate("Plains")); + } + + TitheEffect() { + super(Outcome.Benefit); + this.staticText = "Search your library for a Plains card. If target opponent controls more lands than you, you may search your library for an additional Plains card. Reveal those cards and put them into your hand. Then shuffle your library"; + } + + TitheEffect(final TitheEffect effect) { + super(effect); + } + + @Override + public TitheEffect copy() { + return new TitheEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + int numYourLands = game.getBattlefield().countAll(new FilterLandPermanent(), source.getControllerId(), game); + int numOpponentLands = game.getBattlefield().countAll(new FilterLandPermanent(), this.getTargetPointer().getFirst(game, source), game); + new SearchLibraryPutInHandEffect(new TargetCardInLibrary(0, (numOpponentLands > numYourLands ? 2 : 1), filter), true).apply(game, source); + return true; + } +} diff --git a/Mage/src/mage/abilities/condition/common/OpponentControllsMoreCondition.java b/Mage/src/mage/abilities/condition/common/OpponentControlsMoreCondition.java similarity index 92% rename from Mage/src/mage/abilities/condition/common/OpponentControllsMoreCondition.java rename to Mage/src/mage/abilities/condition/common/OpponentControlsMoreCondition.java index 8a8183af34..f4a0ccc106 100644 --- a/Mage/src/mage/abilities/condition/common/OpponentControllsMoreCondition.java +++ b/Mage/src/mage/abilities/condition/common/OpponentControlsMoreCondition.java @@ -39,11 +39,11 @@ import mage.game.Game; * @author LevelX2 */ -public class OpponentControllsMoreCondition implements Condition { +public class OpponentControlsMoreCondition implements Condition { private final FilterPermanent filter; - public OpponentControllsMoreCondition(FilterPermanent filter) { + public OpponentControlsMoreCondition(FilterPermanent filter) { this.filter = filter; } diff --git a/Mage/src/mage/abilities/keyword/CumulativeUpkeepAbility.java b/Mage/src/mage/abilities/keyword/CumulativeUpkeepAbility.java index 199c853610..4077074fa7 100644 --- a/Mage/src/mage/abilities/keyword/CumulativeUpkeepAbility.java +++ b/Mage/src/mage/abilities/keyword/CumulativeUpkeepAbility.java @@ -25,8 +25,6 @@ * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ - - package mage.abilities.keyword; import mage.abilities.Ability; @@ -41,6 +39,8 @@ import mage.constants.Outcome; import mage.constants.TargetController; import mage.counters.CounterType; import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; import mage.game.permanent.Permanent; import mage.players.Player; @@ -48,12 +48,10 @@ import mage.players.Player; * * @author Plopman */ - - public class CumulativeUpkeepAbility extends BeginningOfUpkeepTriggeredAbility { - + private Cost cumulativeCost; - + public CumulativeUpkeepAbility(Cost cumulativeCost) { super(new AddCountersSourceEffect(CounterType.AGE.createInstance()), TargetController.YOU, false); this.addEffect(new CumulativeUpkeepEffect(cumulativeCost)); @@ -82,9 +80,9 @@ public class CumulativeUpkeepAbility extends BeginningOfUpkeepTriggeredAbility { } class CumulativeUpkeepEffect extends OneShotEffect { - - private Cost cumulativeCost; - + + private final Cost cumulativeCost; + CumulativeUpkeepEffect(Cost cumulativeCost) { super(Outcome.Sacrifice); this.cumulativeCost = cumulativeCost; @@ -95,46 +93,44 @@ class CumulativeUpkeepEffect extends OneShotEffect { this.cumulativeCost = effect.cumulativeCost.copy(); } - @Override public boolean apply(Game game, Ability source) { Player player = game.getPlayer(source.getControllerId()); Permanent permanent = game.getPermanent(source.getSourceId()); - if (player != null && permanent != null) { + if (player != null && permanent != null) { int ageCounter = permanent.getCounters().getCount(CounterType.AGE); - if(cumulativeCost instanceof ManaCost){ - ManaCostsImpl totalCost = new ManaCostsImpl(); - for(int i = 0 ; i < ageCounter; i++){ + if (cumulativeCost instanceof ManaCost) { + ManaCostsImpl totalCost = new ManaCostsImpl<>(); + for (int i = 0; i < ageCounter; i++) { totalCost.add((ManaCost) cumulativeCost.copy()); } if (player.chooseUse(Outcome.Benefit, "Pay " + totalCost.getText() + "?", source, game)) { totalCost.clearPaid(); - if (totalCost.payOrRollback(source, game, source.getSourceId(), source.getControllerId())){ + if (totalCost.payOrRollback(source, game, source.getSourceId(), source.getControllerId())) { return true; } } + game.fireEvent(new GameEvent(EventType.DIDNT_PAY_CUMULATIVE_UPKEEP, permanent.getId(), permanent.getId(), player.getId(), ageCounter, false)); permanent.sacrifice(source.getSourceId(), game); - return true; - } - else{ - CostsImpl totalCost = new CostsImpl(); - for(int i = 0 ; i < ageCounter; i++){ + return true; + } else { + CostsImpl totalCost = new CostsImpl<>(); + for (int i = 0; i < ageCounter; i++) { totalCost.add(cumulativeCost.copy()); } if (player.chooseUse(Outcome.Benefit, totalCost.getText() + "?", source, game)) { totalCost.clearPaid(); int bookmark = game.bookmarkState(); - if (totalCost.pay(source, game, source.getSourceId(), source.getControllerId(), false)){ + if (totalCost.pay(source, game, source.getSourceId(), source.getControllerId(), false)) { return true; - } - else{ + } else { game.restoreState(bookmark, source.getRule()); } } + game.fireEvent(new GameEvent(EventType.DIDNT_PAY_CUMULATIVE_UPKEEP, permanent.getId(), permanent.getId(), player.getId(), ageCounter, false)); permanent.sacrifice(source.getSourceId(), game); - return true; + return true; } - } return false; } diff --git a/Mage/src/mage/game/events/GameEvent.java b/Mage/src/mage/game/events/GameEvent.java index 93d4cef024..a6909fe729 100644 --- a/Mage/src/mage/game/events/GameEvent.java +++ b/Mage/src/mage/game/events/GameEvent.java @@ -185,6 +185,7 @@ public class GameEvent implements Serializable { ENCHANT_PLAYER, ENCHANTED_PLAYER, CAN_TAKE_MULLIGAN, FLIP_COIN, COIN_FLIPPED, SCRY, FATESEAL, + DIDNT_PAY_CUMULATIVE_UPKEEP, //permanent events ENTERS_THE_BATTLEFIELD, TAP, TAPPED, TAPPED_FOR_MANA, @@ -241,7 +242,6 @@ public class GameEvent implements Serializable { //combat events COMBAT_DAMAGE_APPLIED, SELECTED_ATTACKER, SELECTED_BLOCKER; - } public GameEvent(EventType type, UUID targetId, UUID sourceId, UUID playerId) {