From 8e1ef15b7027d8463ffbe20c28c8614912db040f Mon Sep 17 00:00:00 2001 From: Susucre <34709007+Susucre@users.noreply.github.com> Date: Sun, 8 Oct 2023 23:52:36 +0200 Subject: [PATCH] [LCI] Implement Ojer Axonil, Deepest Might (#11195) * [LCI] Implement Ojer Axonil, Deepest Might * add tests * Alter text generation on ActivateIfConditionActivatedAbility to handle "and as a sorcery" --- .../src/mage/cards/h/HeronBlessedGeist.java | 2 +- .../mage/cards/o/OjerAxonilDeepestMight.java | 149 ++++++++++++++ .../src/mage/cards/s/SpeakerOfTheHeavens.java | 17 +- Mage.Sets/src/mage/cards/t/TempleOfPower.java | 157 ++++++++++++++ .../src/mage/sets/LostCavernsOfIxalan.java | 2 + .../lci/OjerAxonilDeepestMightTest.java | 194 ++++++++++++++++++ .../ActivateIfConditionActivatedAbility.java | 13 +- 7 files changed, 521 insertions(+), 13 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/o/OjerAxonilDeepestMight.java create mode 100644 Mage.Sets/src/mage/cards/t/TempleOfPower.java create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/single/lci/OjerAxonilDeepestMightTest.java diff --git a/Mage.Sets/src/mage/cards/h/HeronBlessedGeist.java b/Mage.Sets/src/mage/cards/h/HeronBlessedGeist.java index d63452acafd..2578da43695 100644 --- a/Mage.Sets/src/mage/cards/h/HeronBlessedGeist.java +++ b/Mage.Sets/src/mage/cards/h/HeronBlessedGeist.java @@ -28,7 +28,7 @@ import java.util.UUID; public final class HeronBlessedGeist extends CardImpl { private static final Condition condition = new PermanentsOnTheBattlefieldCondition( - new FilterEnchantmentPermanent("you control an enchantment and only as a sorcery") + new FilterEnchantmentPermanent("you control an enchantment") ); private static final Hint hint = new ConditionHint(condition, "You control an enchantment"); diff --git a/Mage.Sets/src/mage/cards/o/OjerAxonilDeepestMight.java b/Mage.Sets/src/mage/cards/o/OjerAxonilDeepestMight.java new file mode 100644 index 00000000000..d17fe96fa19 --- /dev/null +++ b/Mage.Sets/src/mage/cards/o/OjerAxonilDeepestMight.java @@ -0,0 +1,149 @@ +package mage.cards.o; + +import mage.MageInt; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.common.DiesSourceTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.abilities.keyword.TrampleAbility; +import mage.abilities.keyword.TransformAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.game.Game; +import mage.game.events.DamageEvent; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.players.Player; + +import java.util.UUID; + +/** + * @author Susucr + */ +public final class OjerAxonilDeepestMight extends CardImpl { + + public OjerAxonilDeepestMight(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}{R}"); + this.secondSideCardClazz = mage.cards.t.TempleOfPower.class; + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.GOD); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // Trample + this.addAbility(TrampleAbility.getInstance()); + + // If a red source you control would deal an amount of noncombat damage less than Ojer Axonil's power to an opponent, that source deals damage equal to Ojer Axonil's power instead. + this.addAbility(new SimpleStaticAbility(new OjerAxonilDeepestMightReplacementEffect())); + + // When Ojer Axonil dies, return it to the battlefield tapped and transformed under its owner's control. + this.addAbility(new TransformAbility()); + this.addAbility(new DiesSourceTriggeredAbility(new OjerAxonilDeepestMightTransformEffect())); + } + + private OjerAxonilDeepestMight(final OjerAxonilDeepestMight card) { + super(card); + } + + @Override + public OjerAxonilDeepestMight copy() { + return new OjerAxonilDeepestMight(this); + } +} + +// Inspired by Edgar, Charmed Groom +class OjerAxonilDeepestMightTransformEffect extends OneShotEffect { + + OjerAxonilDeepestMightTransformEffect() { + super(Outcome.Benefit); + staticText = "return it to the battlefield tapped and transformed under its owner's control"; + } + + private OjerAxonilDeepestMightTransformEffect(final OjerAxonilDeepestMightTransformEffect effect) { + super(effect); + } + + @Override + public OjerAxonilDeepestMightTransformEffect copy() { + return new OjerAxonilDeepestMightTransformEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return false; + } + MageObject sourceObject = source.getSourceObjectIfItStillExists(game); + if (!(sourceObject instanceof Card)) { + return false; + } + game.getState().setValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + source.getSourceId(), Boolean.TRUE); + controller.moveCards((Card) sourceObject, Zone.BATTLEFIELD, source, game, true, false, true, null); + return true; + } +} + +// Inspired by Torbran, Thane of Red Fell +class OjerAxonilDeepestMightReplacementEffect extends ReplacementEffectImpl { + + OjerAxonilDeepestMightReplacementEffect() { + super(Duration.WhileOnBattlefield, Outcome.Damage); + this.staticText = "If a red source you control would deal an amount of noncombat damage less " + + "than {this}'s power to an opponent, that source deals damage equal to {this}'s power instead."; + } + + private OjerAxonilDeepestMightReplacementEffect(final OjerAxonilDeepestMightReplacementEffect effect) { + super(effect); + } + + @Override + public OjerAxonilDeepestMightReplacementEffect copy() { + return new OjerAxonilDeepestMightReplacementEffect(this); + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + Permanent ojer = source.getSourcePermanentIfItStillExists(game); + if (ojer != null && ojer.getPower().getValue() > 0) { + event.setAmount(ojer.getPower().getValue()); + } + return false; + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DAMAGE_PLAYER; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + Player controller = game.getPlayer(source.getControllerId()); + // Is damage to an opponent? + if (controller == null || !controller.hasOpponent(event.getTargetId(), game)) { + return false; + } + MageObject sourceObject; + Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(event.getSourceId()); + if (sourcePermanent == null) { + sourceObject = game.getObject(event.getSourceId()); + } else { + sourceObject = sourcePermanent; + } + Permanent ojer = source.getSourcePermanentIfItStillExists(game); + DamageEvent dmgEvent = (DamageEvent) event; + + return sourceObject != null + && ojer != null + && dmgEvent != null + && sourceObject.getColor(game).isRed() + && !dmgEvent.isCombatDamage() + && event.getAmount() > 0 + && event.getAmount() < ojer.getPower().getValue(); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SpeakerOfTheHeavens.java b/Mage.Sets/src/mage/cards/s/SpeakerOfTheHeavens.java index a2e8a69cf5c..7a44172c84e 100644 --- a/Mage.Sets/src/mage/cards/s/SpeakerOfTheHeavens.java +++ b/Mage.Sets/src/mage/cards/s/SpeakerOfTheHeavens.java @@ -2,10 +2,9 @@ package mage.cards.s; import mage.MageInt; import mage.abilities.Ability; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.condition.Condition; -import mage.abilities.condition.common.MainPhaseStackEmptyCondition; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.decorator.ConditionalActivatedAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.keyword.LifelinkAbility; import mage.abilities.keyword.VigilanceAbility; @@ -13,6 +12,7 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; +import mage.constants.TimingRule; import mage.constants.Zone; import mage.game.Game; import mage.game.permanent.token.AngelToken; @@ -39,10 +39,11 @@ public final class SpeakerOfTheHeavens extends CardImpl { // Lifelink this.addAbility(LifelinkAbility.getInstance()); - // {T}: Create a 4/4 white Angel creature token with flying. Activate this ability only if you have at least 7 more life than your starting life total and only any time you could cast a sorcery. - this.addAbility(new ConditionalActivatedAbility( + // {T}: Create a 4/4 white Angel creature token with flying. Activate only if you have at least 7 more life than your starting life total and only as a sorcery. + this.addAbility(new ActivateIfConditionActivatedAbility( Zone.BATTLEFIELD, new CreateTokenEffect(new AngelToken()), - new TapSourceCost(), SpeakerOfTheHeavensCondition.instance + new TapSourceCost(), SpeakerOfTheHeavensCondition.instance, + TimingRule.SORCERY )); } @@ -61,10 +62,6 @@ enum SpeakerOfTheHeavensCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - if (!MainPhaseStackEmptyCondition.instance.apply(game, source) - || !game.isActivePlayer(source.getControllerId())) { - return false; - } Player player = game.getPlayer(source.getControllerId()); if (player == null || player.getLife() < game.getStartingLife() + 7) { return false; @@ -74,6 +71,6 @@ enum SpeakerOfTheHeavensCondition implements Condition { @Override public String toString() { - return "you have at least 7 life more than your starting life total and only as a sorcery"; + return "you have at least 7 life more than your starting life total"; } } diff --git a/Mage.Sets/src/mage/cards/t/TempleOfPower.java b/Mage.Sets/src/mage/cards/t/TempleOfPower.java new file mode 100644 index 00000000000..108d6ce97ee --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TempleOfPower.java @@ -0,0 +1,157 @@ +package mage.cards.t; + +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.common.ActivateIfConditionActivatedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.Condition; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.InfoEffect; +import mage.abilities.effects.common.TransformSourceEffect; +import mage.abilities.hint.Hint; +import mage.abilities.mana.RedManaAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.TimingRule; +import mage.constants.WatcherScope; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.DamagedEvent; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.game.stack.StackObject; +import mage.watchers.Watcher; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +/** + * @author Susucr + */ +public final class TempleOfPower extends CardImpl { + + public TempleOfPower(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); + this.nightCard = true; + + // (Transforms from Ojer Axonil, Deepest Might.) + Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new InfoEffect("(Transforms from Ojer Axonil, Deepest Might.)")); + ability.setRuleAtTheTop(true); + this.addAbility(ability); + + // {T}: Add {R}. + this.addAbility(new RedManaAbility()); + + // {2}{R}, {T}: Transform Temple of Power. Activate only if red sources you controlled dealt 4 or more noncombat damage this turn and only as a sorcery. + ability = new ActivateIfConditionActivatedAbility( + Zone.BATTLEFIELD, + new TransformSourceEffect(), + new ManaCostsImpl("{2}{R}"), + TempleOfPowerCondition.instance, + TimingRule.SORCERY + ); + ability.addWatcher(new TempleOfPowerWatcher()); + ability.addCost(new TapSourceCost()); + ability.addHint(TempleOfPowerHint.instance); + this.addAbility(ability); + } + + private TempleOfPower(final TempleOfPower card) { + super(card); + } + + @Override + public TempleOfPower copy() { + return new TempleOfPower(this); + } +} + +enum TempleOfPowerCondition implements Condition { + instance; + + @Override + public boolean apply(Game game, Ability source) { + TempleOfPowerWatcher watcher = game.getState().getWatcher(TempleOfPowerWatcher.class); + return watcher != null + && 4 <= watcher.damageForPlayer(source.getControllerId()); + } + + @Override + public String toString() { + return "if red sources you controlled dealt 4 or more noncombat damage this turn"; + } +} + +enum TempleOfPowerHint implements Hint { + instance; + + @Override + public String getText(Game game, Ability ability) { + TempleOfPowerWatcher watcher = game.getState().getWatcher(TempleOfPowerWatcher.class); + if (watcher == null) { + return ""; + } + + return "Non-combat damage from red source: " + + watcher.damageForPlayer(ability.getControllerId()); + } + + @Override + public TempleOfPowerHint copy() { + return instance; + } +} + +class TempleOfPowerWatcher extends Watcher { + + // player -> total non combat damage from red source controlled by that player dealt this turn. + private final Map damageMap = new HashMap<>(); + + public TempleOfPowerWatcher() { + super(WatcherScope.GAME); + } + + @Override + public void watch(GameEvent event, Game game) { + if (event.getType() == GameEvent.EventType.DAMAGED_PLAYER + || event.getType() == GameEvent.EventType.DAMAGED_PERMANENT) { + DamagedEvent dmgEvent = (DamagedEvent) event; + + // watch only non combat damage events. + if (dmgEvent == null || dmgEvent.isCombatDamage()) { + return; + } + + MageObject sourceObject; + UUID sourceControllerId; + Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(event.getSourceId()); + if (sourcePermanent == null) { + sourceObject = game.getSpellOrLKIStack(event.getSourceId()); + sourceControllerId = ((StackObject) sourceObject).getControllerId(); + } else { + sourceObject = sourcePermanent; + sourceControllerId = sourcePermanent.getControllerId(); + } + + // watch only red sources dealing damage + if (sourceObject == null || !sourceObject.getColor().isRed()) { + return; + } + + damageMap.compute(sourceControllerId, (k, i) -> (i == null ? 0 : i) + event.getAmount()); + } + } + + @Override + public void reset() { + damageMap.clear(); + super.reset(); + } + + int damageForPlayer(UUID playerId) { + return damageMap.getOrDefault(playerId, 0); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/LostCavernsOfIxalan.java b/Mage.Sets/src/mage/sets/LostCavernsOfIxalan.java index e881808755f..e2d90bfa7a3 100644 --- a/Mage.Sets/src/mage/sets/LostCavernsOfIxalan.java +++ b/Mage.Sets/src/mage/sets/LostCavernsOfIxalan.java @@ -26,7 +26,9 @@ public final class LostCavernsOfIxalan extends ExpansionSet { cards.add(new SetCardInfo("Ghalta, Stampede Tyrant", 185, Rarity.MYTHIC, mage.cards.g.GhaltaStampedeTyrant.class)); cards.add(new SetCardInfo("Island", 288, Rarity.LAND, mage.cards.basiclands.Island.class, FULL_ART_BFZ_VARIOUS)); cards.add(new SetCardInfo("Mountain", 290, Rarity.LAND, mage.cards.basiclands.Mountain.class, FULL_ART_BFZ_VARIOUS)); + cards.add(new SetCardInfo("Ojer Axonil, Deepest Might", 317, Rarity.MYTHIC, mage.cards.o.OjerAxonilDeepestMight.class)); cards.add(new SetCardInfo("Plains", 287, Rarity.LAND, mage.cards.basiclands.Plains.class, FULL_ART_BFZ_VARIOUS)); cards.add(new SetCardInfo("Swamp", 289, Rarity.LAND, mage.cards.basiclands.Swamp.class, FULL_ART_BFZ_VARIOUS)); + cards.add(new SetCardInfo("Temple of Power", 317, Rarity.MYTHIC, mage.cards.t.TempleOfPower.class)); } } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/lci/OjerAxonilDeepestMightTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/lci/OjerAxonilDeepestMightTest.java new file mode 100644 index 00000000000..b3041b950a6 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/lci/OjerAxonilDeepestMightTest.java @@ -0,0 +1,194 @@ + +package org.mage.test.cards.single.lci; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author Susucr + */ +public class OjerAxonilDeepestMightTest extends CardTestPlayerBase { + + /** + * Ojer Axonil, Deepest Might + * {2}{R}{R} + * Legendary Creature — God + * + * Trample + * If a red source you control would deal an amount of noncombat damage less than Ojer Axonil’s power to an opponent, that source deals damage equal to Ojer Axonil’s power instead. + * When Ojer Axonil dies, return it to the battlefield tapped and transformed under its owner’s control. + * 4/4 + * + * Temple of Power + * Land + * + * (Transforms from Ojer Axonil, Deepest Might.) + * {T}: Add {R}. + * {2}{R}, {T}: Transform Temple of Power. Activate only if red sources you controlled dealt 4 or more noncombat damage this turn and only as a sorcery. + */ + private static final String ojer = "Ojer Axonil, Deepest Might"; + private static final String temple = "Temple of Power"; + private static final String templeTransformAbility = "{2}{R}, {T}: Transform {this}. Activate only if red sources you controlled dealt 4 or more noncombat damage this turn and only as a sorcery."; + + /** + * Lightning Bolt + * {R} + * Instant + * + * Lightning Bolt deals 3 damage to any target. + */ + private static final String bolt = "Lightning Bolt"; + /** + * Lava Axe + * {4}{R} + * Sorcery + * + * Lava Axe deals 5 damage to target player or planeswalker. + */ + private static final String axe = "Lava Axe"; + + @Test + public void testReplacement_BoltFace() { + setStrictChooseMode(true); + + addCard(Zone.BATTLEFIELD, playerA, ojer, 1); + addCard(Zone.HAND, playerA, bolt, 1); + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, bolt, playerB); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertLife(playerB, 20 - 4); + } + + @Test + public void testReplacement_BoltOwnFace() { + setStrictChooseMode(true); + + addCard(Zone.BATTLEFIELD, playerA, ojer, 1); + addCard(Zone.HAND, playerA, bolt, 1); + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, bolt, playerA); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertLife(playerA, 20 - 3); // only work on opponnent + } + + @Test + public void testReplacement_BoltOjer() { + setStrictChooseMode(true); + + addCard(Zone.BATTLEFIELD, playerA, ojer, 1); + addCard(Zone.HAND, playerA, bolt, 1); + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, bolt, ojer); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertDamageReceived(playerA, ojer, 3); // does not work on creatures + } + + @Test + public void testReplacement_CombatDamageNotReplaced() { + setStrictChooseMode(true); + + addCard(Zone.BATTLEFIELD, playerA, ojer, 1); + addCard(Zone.BATTLEFIELD, playerA, "Raging Goblin", 1); + + attack(1, playerA, "Raging Goblin", playerB); + + setStopAt(1, PhaseStep.END_COMBAT); + execute(); + + assertLife(playerB, 20 - 1); // does not alter combat damage + } + + @Test + public void testReplacement_Hellrider() { + setStrictChooseMode(true); + + addCard(Zone.BATTLEFIELD, playerA, ojer, 1); + // Whenever a creature you control attacks, Hellrider deals 1 damage to the player or planeswalker it’s attacking. + addCard(Zone.BATTLEFIELD, playerA, "Hellrider", 1); + addCard(Zone.BATTLEFIELD, playerA, "Raging Goblin", 1); + + attack(1, playerA, "Raging Goblin", playerB); + + setStopAt(1, PhaseStep.END_COMBAT); + execute(); + + assertLife(playerB, 20 - 1 - 4); // Hellrider's trigger is altered. + } + + @Test + public void testReplacement_LavaAxeFace() { + setStrictChooseMode(true); + + addCard(Zone.BATTLEFIELD, playerA, ojer, 1); + addCard(Zone.HAND, playerA, axe, 1); + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 5); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, axe, playerB); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertLife(playerB, 20 - 5); // no replacement + } + + @Test + public void testReplacement_GiantGrowth_LavaAxeFace() { + setStrictChooseMode(true); + + addCard(Zone.BATTLEFIELD, playerA, ojer, 1); + addCard(Zone.HAND, playerA, axe, 1); + addCard(Zone.HAND, playerA, "Giant Growth", 1); // +3/+3 until end of turn + addCard(Zone.BATTLEFIELD, playerA, "Taiga", 6); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, axe, playerB); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Giant Growth", ojer); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertLife(playerB, 20 - (4 + 3)); + } + + @Test + public void testTransform() { + setStrictChooseMode(true); + + addCard(Zone.BATTLEFIELD, playerA, ojer, 1); + addCard(Zone.HAND, playerA, axe, 1); + addCard(Zone.HAND, playerA, "Bathe in Dragonfire", 1); // 4 damage to target creature + addCard(Zone.BATTLEFIELD, playerA, "Battlefield Forge", 5 + 3); // Using Forge to distinguish the mana ability from the Temple one. + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Bathe in Dragonfire", ojer, true); + checkPermanentTapped("temple in play", 1, PhaseStep.PRECOMBAT_MAIN, playerA, temple, true, 1); + + checkPlayableAbility("condition false", 3, PhaseStep.PRECOMBAT_MAIN, playerA, templeTransformAbility, false); + activateManaAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}. {this} deals 1 damage to you.", 5); + castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, axe, playerB); + waitStackResolved(3, PhaseStep.PRECOMBAT_MAIN); + activateManaAbility(3, PhaseStep.POSTCOMBAT_MAIN, playerA, "{T}: Add {R}. {this} deals 1 damage to you.", 3); + checkPlayableAbility("condition true", 3, PhaseStep.POSTCOMBAT_MAIN, playerA, templeTransformAbility, true); + activateAbility(3, PhaseStep.POSTCOMBAT_MAIN, playerA, templeTransformAbility); + + setStopAt(3, PhaseStep.END_TURN); + execute(); + + assertLife(playerB, 20 - 5); + assertPermanentCount(playerA, ojer, 1); + assertTapped(ojer, true); + } +} diff --git a/Mage/src/main/java/mage/abilities/common/ActivateIfConditionActivatedAbility.java b/Mage/src/main/java/mage/abilities/common/ActivateIfConditionActivatedAbility.java index 35243e7218f..31eae736390 100644 --- a/Mage/src/main/java/mage/abilities/common/ActivateIfConditionActivatedAbility.java +++ b/Mage/src/main/java/mage/abilities/common/ActivateIfConditionActivatedAbility.java @@ -6,6 +6,7 @@ import mage.abilities.condition.Condition; import mage.abilities.condition.InvertCondition; import mage.abilities.costs.Cost; import mage.abilities.effects.Effect; +import mage.constants.TimingRule; import mage.constants.Zone; import mage.game.Game; @@ -13,10 +14,14 @@ import mage.game.Game; * @author LevelX2 */ public class ActivateIfConditionActivatedAbility extends ActivatedAbilityImpl { - public ActivateIfConditionActivatedAbility(Zone zone, Effect effect, Cost cost, Condition condition) { + this(zone, effect, cost, condition, TimingRule.INSTANT); + } + + public ActivateIfConditionActivatedAbility(Zone zone, Effect effect, Cost cost, Condition condition, TimingRule timing) { super(zone, effect, cost); this.condition = condition; + this.timing = timing; } protected ActivateIfConditionActivatedAbility(final ActivateIfConditionActivatedAbility ability) { @@ -41,7 +46,11 @@ public class ActivateIfConditionActivatedAbility extends ActivatedAbilityImpl { && !condition.toString().startsWith("if")) { sb.append("if "); } - sb.append(condition.toString()).append('.'); + sb.append(condition.toString()); + if (timing == TimingRule.SORCERY) { + sb.append(" and only as a sorcery"); + } + sb.append('.'); return sb.toString(); }