diff --git a/Mage.Sets/src/mage/sets/magic2010/SoulWarden.java b/Mage.Sets/src/mage/sets/magic2010/SoulWarden.java index 5310991e3c3..a84fcd66d1f 100644 --- a/Mage.Sets/src/mage/sets/magic2010/SoulWarden.java +++ b/Mage.Sets/src/mage/sets/magic2010/SoulWarden.java @@ -1,16 +1,16 @@ /* * 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 @@ -20,26 +20,24 @@ * 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.magic2010; import java.util.UUID; -import mage.constants.CardType; -import mage.constants.Rarity; import mage.MageInt; import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.effects.common.GainLifeEffect; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; import mage.filter.FilterPermanent; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.AnotherPredicate; - /** * * @author BetaSteward_at_googlemail.com @@ -47,6 +45,7 @@ import mage.filter.predicate.permanent.AnotherPredicate; public class SoulWarden extends CardImpl { private static final FilterPermanent filter = new FilterCreaturePermanent("another creature"); + static { filter.add(new AnotherPredicate()); } @@ -60,6 +59,7 @@ public class SoulWarden extends CardImpl { this.power = new MageInt(1); this.toughness = new MageInt(1); + // Whenever another creature enters the battlefield, you gain 1 life. this.addAbility(new EntersBattlefieldAllTriggeredAbility(new GainLifeEffect(1), filter)); } diff --git a/Mage.Sets/src/mage/sets/returntoravnica/SupremeVerdict.java b/Mage.Sets/src/mage/sets/returntoravnica/SupremeVerdict.java index 3ea105437d5..08dc6f8febb 100644 --- a/Mage.Sets/src/mage/sets/returntoravnica/SupremeVerdict.java +++ b/Mage.Sets/src/mage/sets/returntoravnica/SupremeVerdict.java @@ -25,20 +25,15 @@ * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ - package mage.sets.returntoravnica; import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.CantBeCounteredAbility; -import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.Effect; -import mage.constants.CardType; -import mage.constants.Rarity; -import mage.abilities.effects.common.CantBeCounteredSourceEffect; import mage.abilities.effects.common.DestroyAllEffect; import mage.cards.CardImpl; -import mage.constants.Zone; +import mage.constants.CardType; +import mage.constants.Rarity; import mage.filter.common.FilterCreaturePermanent; /** @@ -47,21 +42,20 @@ import mage.filter.common.FilterCreaturePermanent; */ public class SupremeVerdict extends CardImpl { - public SupremeVerdict (UUID ownerId) { + public SupremeVerdict(UUID ownerId) { super(ownerId, 201, "Supreme Verdict", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{1}{W}{W}{U}"); this.expansionSetCode = "RTR"; - // Supreme Verdict can't be countered. Ability ability = new CantBeCounteredAbility(); ability.setRuleAtTheTop(true); this.addAbility(ability); - // Destroy all creatures. + // Destroy all creatures. this.getSpellAbility().addEffect(new DestroyAllEffect(new FilterCreaturePermanent())); } - public SupremeVerdict (final SupremeVerdict card) { + public SupremeVerdict(final SupremeVerdict card) { super(card); } @@ -69,4 +63,4 @@ public class SupremeVerdict extends CardImpl { public SupremeVerdict copy() { return new SupremeVerdict(this); } -} \ No newline at end of file +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/PersistTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/PersistTest.java index 5f2859f6c1a..a5c8ac00991 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/PersistTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/PersistTest.java @@ -3,7 +3,6 @@ * To change this template file, choose Tools | Templates * and open the template in the editor. */ - package org.mage.test.cards.abilities.keywords; import mage.constants.PhaseStep; @@ -15,33 +14,32 @@ import org.junit.Test; import org.mage.test.serverside.base.CardTestPlayerBase; /** - * 702.78. Persist - * 702.78a Persist is a triggered ability. "Persist" means "When this permanent is put into a graveyard - * from the battlefield, if it had no -1/-1 counters on it, return it to the battlefield under its - * owner's control with a -1/-1 counter on it." + * 702.78. Persist 702.78a Persist is a triggered ability. "Persist" means "When + * this permanent is put into a graveyard from the battlefield, if it had no + * -1/-1 counters on it, return it to the battlefield under its owner's control + * with a -1/-1 counter on it." * * @author LevelX2 */ - public class PersistTest extends CardTestPlayerBase { /** - * Tests Safehold Elite don't returns from Persist if already a -1/-1 counter - * was put on it from another source + * Tests Safehold Elite don't returns from Persist if already a -1/-1 + * counter was put on it from another source * */ @Test public void testUndyingdoesntTriggerWithMinusCounter() { - + // Safehold Elite 2/2 {1}{G/W} // Creature - Elf Scout - // + // // Persist addCard(Zone.BATTLEFIELD, playerA, "Safehold Elite"); // Put a -1/-1 counter on target creature. When that creature dies this turn, its controller gets a poison counter. - addCard(Zone.HAND, playerB, "Virulent Wound",1); - addCard(Zone.HAND, playerB, "Lightning Bolt",1); + addCard(Zone.HAND, playerB, "Virulent Wound", 1); + addCard(Zone.HAND, playerB, "Lightning Bolt", 1); addCard(Zone.BATTLEFIELD, playerB, "Swamp", 1); addCard(Zone.BATTLEFIELD, playerB, "Mountain", 1); @@ -58,9 +56,9 @@ public class PersistTest extends CardTestPlayerBase { Assert.assertEquals(1, playerA.getCounters().getCount(CounterType.POISON)); } - /** - * If a card with persist is removed from a graveyard before the persist ability resolves, persist will do nothing. + * If a card with persist is removed from a graveyard before the persist + * ability resolves, persist will do nothing. */ @Test public void testWontTriggerIfPersistCardIsRemovedFromGraveyard() { @@ -72,14 +70,14 @@ public class PersistTest extends CardTestPlayerBase { addCard(Zone.BATTLEFIELD, playerA, "Safehold Elite"); // Exile target card from a graveyard. You gain 3 life. - addCard(Zone.HAND, playerB, "Lightning Bolt",1); - addCard(Zone.HAND, playerB, "Shadowfeed",1); + addCard(Zone.HAND, playerB, "Lightning Bolt", 1); + addCard(Zone.HAND, playerB, "Shadowfeed", 1); addCard(Zone.BATTLEFIELD, playerB, "Swamp", 1); addCard(Zone.BATTLEFIELD, playerB, "Mountain", 1); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Lightning Bolt", "Safehold Elite"); - castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Shadowfeed", "Safehold Elite","Persist (When this creature dies, if it had no -1/-1 counters on it, return it to the battlefield under its owner's control with a -1/-1 counter on it.)"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Shadowfeed", "Safehold Elite", "Persist (When this creature dies, if it had no -1/-1 counters on it, return it to the battlefield under its owner's control with a -1/-1 counter on it.)"); setStopAt(1, PhaseStep.END_TURN); execute(); @@ -103,11 +101,11 @@ public class PersistTest extends CardTestPlayerBase { addCard(Zone.BATTLEFIELD, playerA, "Kitchen Finks", 1); /** - * Deathtouch, lifelink - * When Wurmcoil Engine dies, put a 3/3 colorless Wurm artifact creature token with - * deathtouch and a 3/3 colorless Wurm artifact creature token with lifelink onto the battlefield. + * Deathtouch, lifelink When Wurmcoil Engine dies, put a 3/3 colorless + * Wurm artifact creature token with deathtouch and a 3/3 colorless Wurm + * artifact creature token with lifelink onto the battlefield. */ - addCard(Zone.BATTLEFIELD, playerB, "Wurmcoil Engine",1); + addCard(Zone.BATTLEFIELD, playerB, "Wurmcoil Engine", 1); attack(2, playerB, "Wurmcoil Engine"); block(2, playerA, "Kitchen Finks", "Wurmcoil Engine"); @@ -117,14 +115,13 @@ public class PersistTest extends CardTestPlayerBase { assertPermanentCount(playerB, "Wurmcoil Engine", 1); assertPermanentCount(playerA, "Kitchen Finks", 1); - assertPowerToughness(playerA, "Kitchen Finks", 2,1); + assertPowerToughness(playerA, "Kitchen Finks", 2, 1); assertLife(playerA, 22); // Kitchen Finks +2 life assertLife(playerB, 26); // Wurmcoil Engine +6 ife } - @Test public void testInteractionWithToporOrb() { @@ -137,12 +134,12 @@ public class PersistTest extends CardTestPlayerBase { addCard(Zone.BATTLEFIELD, playerA, "Kitchen Finks", 2); /** - * Deathtouch, lifelink - * When Wurmcoil Engine dies, put a 3/3 colorless Wurm artifact creature token with - * deathtouch and a 3/3 colorless Wurm artifact creature token with lifelink onto the battlefield. + * Deathtouch, lifelink When Wurmcoil Engine dies, put a 3/3 colorless + * Wurm artifact creature token with deathtouch and a 3/3 colorless Wurm + * artifact creature token with lifelink onto the battlefield. */ - addCard(Zone.BATTLEFIELD, playerB, "Wurmcoil Engine",1); - addCard(Zone.BATTLEFIELD, playerB, "Torpor Orb",1); + addCard(Zone.BATTLEFIELD, playerB, "Wurmcoil Engine", 1); + addCard(Zone.BATTLEFIELD, playerB, "Torpor Orb", 1); attack(2, playerB, "Wurmcoil Engine"); block(2, playerA, "Kitchen Finks", "Wurmcoil Engine"); @@ -161,9 +158,44 @@ public class PersistTest extends CardTestPlayerBase { assertPermanentCount(playerB, "Wurm", 2); assertPermanentCount(playerA, "Kitchen Finks", 2); assertPowerToughness(playerA, "Kitchen Finks", 2, 1, Filter.ComparisonScope.All); - + } + /** + * Situation: Clever Impersonator is copying ". Opponent casts Supreme + * Verdict. Persist on the clone of Glen Elendra Archmage triggers and goes + * on the stack, and I am asked to put triggers on the stack. Problem: No + * options pop up. I tried pressing many buttons, but the game was + * deadlocked. + */ + @Test + public void testCopiedCreatureWithPersists() { - // some tests were moved to LastKnownInformationTest + // Flying + // {U}, Sacrifice Glen Elendra Archmage: Counter target noncreature spell. + // Persist + addCard(Zone.BATTLEFIELD, playerB, "Glen Elendra Archmage", 1); // 2/2 + addCard(Zone.BATTLEFIELD, playerB, "Plains", 2); + addCard(Zone.BATTLEFIELD, playerB, "Island", 2); + // Supreme Verdict can't be countered. + // Destroy all creatures. + addCard(Zone.HAND, playerB, "Supreme Verdict", 1); // {1}{W}{W}{U} + + // You may have Clever Impersonator enter the battlefield as a copy of any nonland permanent on the battlefield. + addCard(Zone.HAND, playerA, "Clever Impersonator", 1); + addCard(Zone.BATTLEFIELD, playerA, "Island", 4); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Clever Impersonator"); + setChoice(playerA, "Glen Elendra Archmage"); + + castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Supreme Verdict"); + + setStopAt(2, PhaseStep.BEGIN_COMBAT); + execute(); + + assertPermanentCount(playerB, "Glen Elendra Archmage", 1); + assertPowerToughness(playerB, "Glen Elendra Archmage", 1, 1); + assertPermanentCount(playerA, "Glen Elendra Archmage", 1); + assertPowerToughness(playerA, "Glen Elendra Archmage", 1, 1); + } } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/EntersTheBattlefieldTriggerTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/EntersTheBattlefieldTriggerTest.java new file mode 100644 index 00000000000..fbeebe9d6eb --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/EntersTheBattlefieldTriggerTest.java @@ -0,0 +1,67 @@ +/* + * 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 org.mage.test.cards.triggers; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author LevelX2 + */ +public class EntersTheBattlefieldTriggerTest extends CardTestPlayerBase { + + @Test + public void testDrawCardsAddedCounters() { + addCard(Zone.BATTLEFIELD, playerA, "Plains", 1); + addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion", 1); + addCard(Zone.HAND, playerA, "Soul Warden"); + + // You may have Clever Impersonator enter the battlefield as a copy of any nonland permanent on the battlefield. + addCard(Zone.HAND, playerB, "Clever Impersonator", 1); + addCard(Zone.BATTLEFIELD, playerB, "Island", 4); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Soul Warden"); + + castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Clever Impersonator"); + setChoice(playerB, "Silvercoat Lion"); + + setStopAt(2, PhaseStep.BEGIN_COMBAT); + execute(); + + assertPermanentCount(playerA, "Soul Warden", 1); + assertPermanentCount(playerA, "Silvercoat Lion", 1); + assertPermanentCount(playerB, "Silvercoat Lion", 1); + + assertLife(playerA, 21); + assertLife(playerB, 20); + } + +} diff --git a/Mage/src/mage/abilities/keyword/PersistAbility.java b/Mage/src/mage/abilities/keyword/PersistAbility.java index 2577fec20eb..3f4a297c7de 100644 --- a/Mage/src/mage/abilities/keyword/PersistAbility.java +++ b/Mage/src/mage/abilities/keyword/PersistAbility.java @@ -1,50 +1,45 @@ /* -* 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. -*/ - + * 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.keyword; import mage.abilities.Ability; import mage.abilities.common.DiesTriggeredAbility; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.ReplacementEffectImpl; import mage.abilities.effects.common.ReturnSourceFromGraveyardToBattlefieldEffect; -import mage.constants.Duration; import mage.constants.Outcome; import mage.counters.CounterType; +import mage.counters.Counters; import mage.game.Game; -import mage.game.events.EntersTheBattlefieldEvent; import mage.game.events.GameEvent; import mage.game.events.ZoneChangeEvent; import mage.game.permanent.Permanent; import mage.target.targetpointer.FixedTarget; - - public class PersistAbility extends DiesTriggeredAbility { public PersistAbility() { @@ -73,7 +68,6 @@ public class PersistAbility extends DiesTriggeredAbility { if (permanent.getCounters().getCount(CounterType.M1M1) == 0) { FixedTarget fixedTarget = new FixedTarget(permanent.getId()); fixedTarget.init(game, this); - game.getState().setValue("persist" + getSourceId().toString(), fixedTarget); return true; } } @@ -104,58 +98,9 @@ class PersistEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - game.addEffect(new PersistReplacementEffect(), source); + Counters countersToAdd = new Counters(); + countersToAdd.addCounter(CounterType.M1M1.createInstance()); + game.setEnterWithCounters(source.getSourceId(), countersToAdd); return true; } } - -class PersistReplacementEffect extends ReplacementEffectImpl { - - PersistReplacementEffect() { - super(Duration.Custom, Outcome.UnboostCreature, false); - selfScope = true; - staticText = "return it to the battlefield under its owner's control with a -1/-1 counter on it"; - } - - PersistReplacementEffect(final PersistReplacementEffect effect) { - super(effect); - } - - @Override - public PersistReplacementEffect copy() { - return new PersistReplacementEffect(this); - } - - @Override - public boolean replaceEvent(GameEvent event, Ability source, Game game) { - Permanent permanent = game.getPermanent(event.getTargetId()); - if (permanent != null) { - permanent.addCounters(CounterType.M1M1.createInstance(), game); - } - discard(); - return false; - } - - @Override - public boolean checksEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD; - } - - @Override - public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getTargetId().equals(source.getSourceId())) { - Object fixedTarget = game.getState().getValue("persist" + source.getSourceId().toString()); - if (fixedTarget instanceof FixedTarget && ((FixedTarget) fixedTarget).getTarget().equals(source.getSourceId()) && - ((FixedTarget) fixedTarget).getZoneChangeCounter() + 1 == game.getState().getZoneChangeCounter(source.getSourceId())) { - - return true; - } - } - return false; - } - - @Override - public boolean apply(Game game, Ability source) { - return false; - } -} diff --git a/Mage/src/mage/abilities/keyword/UndyingAbility.java b/Mage/src/mage/abilities/keyword/UndyingAbility.java index 0f5b2636c67..237989397a2 100644 --- a/Mage/src/mage/abilities/keyword/UndyingAbility.java +++ b/Mage/src/mage/abilities/keyword/UndyingAbility.java @@ -1,16 +1,13 @@ package mage.abilities.keyword; - -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.DiesTriggeredAbility; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.ReplacementEffectImpl; import mage.abilities.effects.common.ReturnSourceFromGraveyardToBattlefieldEffect; -import mage.constants.Duration; import mage.constants.Outcome; import mage.constants.Zone; import mage.counters.CounterType; +import mage.counters.Counters; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; @@ -19,7 +16,7 @@ import mage.game.permanent.Permanent; * @author Loki */ public class UndyingAbility extends DiesTriggeredAbility { - + public UndyingAbility() { super(new UndyingEffect()); this.addEffect(new ReturnSourceFromGraveyardToBattlefieldEffect(false, true)); @@ -39,7 +36,6 @@ public class UndyingAbility extends DiesTriggeredAbility { if (super.checkTrigger(event, game)) { Permanent permanent = (Permanent) game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD); if (!permanent.getCounters().containsKey(CounterType.P1P1) || permanent.getCounters().getCount(CounterType.P1P1) == 0) { - game.getState().setValue("undying" + getSourceId(),permanent.getId()); return true; } } @@ -70,58 +66,9 @@ class UndyingEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - game.addEffect(new UndyingReplacementEffect(), source); - return false; - } -} - -class UndyingReplacementEffect extends ReplacementEffectImpl { - - UndyingReplacementEffect() { - super(Duration.OneUse, Outcome.BoostCreature, false); - selfScope = true; - staticText = "return it to the battlefield under its owner's control with a +1/+1 counter on it"; - } - - UndyingReplacementEffect(final UndyingReplacementEffect effect) { - super(effect); - } - - @Override - public UndyingReplacementEffect copy() { - return new UndyingReplacementEffect(this); - } - - @Override - public boolean replaceEvent(GameEvent event, Ability source, Game game) { - Permanent permanent = game.getPermanent(event.getTargetId()); - if (permanent != null) { - game.getState().setValue("undying" + source.getSourceId(), null); - permanent.addCounters(CounterType.P1P1.createInstance(), game); - } - used = true; - return false; - } - - @Override - public boolean checksEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD; - } - - @Override - public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getTargetId().equals(source.getSourceId())) { - // Check if undying condition is true - UUID targetId = (UUID) game.getState().getValue("undying" + source.getSourceId()); - if (targetId != null && targetId.equals(source.getSourceId())) { - return true; - } - } - return false; - } - - @Override - public boolean apply(Game game, Ability source) { - return false; + Counters countersToAdd = new Counters(); + countersToAdd.addCounter(CounterType.P1P1.createInstance()); + game.setEnterWithCounters(source.getSourceId(), countersToAdd); + return true; } } diff --git a/Mage/src/mage/cards/CardImpl.java b/Mage/src/mage/cards/CardImpl.java index c353c8e8d31..b72b534d449 100644 --- a/Mage/src/mage/cards/CardImpl.java +++ b/Mage/src/mage/cards/CardImpl.java @@ -602,6 +602,8 @@ public abstract class CardImpl extends MageObjectImpl implements Card { PermanentCard permanent = new PermanentCard(this, event.getPlayerId(), game); // make sure the controller of all continuous effects of this card are switched to the current controller game.getContinuousEffects().setController(objectId, event.getPlayerId()); + // check if there are counters to add to the permanent (e.g. from non replacement effects like Persist) + checkForCountersToAdd(permanent, game); game.addPermanent(permanent); setZone(Zone.BATTLEFIELD, game); game.setScopeRelevant(true); @@ -621,6 +623,16 @@ public abstract class CardImpl extends MageObjectImpl implements Card { return false; } + private void checkForCountersToAdd(PermanentCard permanent, Game game) { + Counters countersToAdd = game.getEnterWithCounters(permanent.getId()); + if (countersToAdd != null) { + for (Counter counter : countersToAdd.values()) { + permanent.addCounters(counter, game); + } + game.setEnterWithCounters(permanent.getId(), null); + } + } + @Override public void setFaceDown(boolean value, Game game) { game.getState().getCardState(objectId).setFaceDown(value); diff --git a/Mage/src/mage/game/Game.java b/Mage/src/mage/game/Game.java index ff69876d5b6..1e0a491f923 100644 --- a/Mage/src/mage/game/Game.java +++ b/Mage/src/mage/game/Game.java @@ -54,6 +54,7 @@ import mage.constants.MultiplayerAttackOption; import mage.constants.PlayerAction; import mage.constants.RangeOfInfluence; import mage.constants.Zone; +import mage.counters.Counters; import mage.game.combat.Combat; import mage.game.command.Commander; import mage.game.command.Emblem; @@ -436,4 +437,8 @@ public interface Game extends MageItem, Serializable { void rollbackTurns(int turnsToRollback); boolean executingRollback(); + + void setEnterWithCounters(UUID sourceId, Counters counters); + + Counters getEnterWithCounters(UUID sourceId); } diff --git a/Mage/src/mage/game/GameImpl.java b/Mage/src/mage/game/GameImpl.java index 2b0cd6990ca..1705dba7ee8 100644 --- a/Mage/src/mage/game/GameImpl.java +++ b/Mage/src/mage/game/GameImpl.java @@ -78,6 +78,7 @@ import mage.constants.PlayerAction; import mage.constants.RangeOfInfluence; import mage.constants.Zone; import mage.counters.CounterType; +import mage.counters.Counters; import mage.filter.Filter; import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledCreaturePermanent; @@ -207,6 +208,9 @@ public abstract class GameImpl implements Game, Serializable { private final int startLife; protected PlayerList playerList; + // used to set the counters a permanent adds the battlefield (if no replacement effect is used e.g. Persist) + protected Map enterWithCounters = new HashMap<>(); + public GameImpl(MultiplayerAttackOption attackOption, RangeOfInfluence range, int freeMulligans, int startLife) { this.id = UUID.randomUUID(); this.range = range; @@ -246,6 +250,7 @@ public abstract class GameImpl implements Game, Serializable { this.priorityTime = game.priorityTime; this.saveGame = game.saveGame; this.startLife = game.startLife; + this.enterWithCounters.putAll(game.enterWithCounters); } @Override @@ -2665,4 +2670,20 @@ public abstract class GameImpl implements Game, Serializable { return executingRollback; } + @Override + public void setEnterWithCounters(UUID sourceId, Counters counters) { + if (counters == null) { + if (enterWithCounters.containsKey(sourceId)) { + enterWithCounters.remove(sourceId); + } + return; + } + enterWithCounters.put(sourceId, counters); + } + + @Override + public Counters getEnterWithCounters(UUID sourceId) { + return enterWithCounters.get(sourceId); + } + }