diff --git a/Mage.Sets/src/mage/cards/a/ArenaOfGlory.java b/Mage.Sets/src/mage/cards/a/ArenaOfGlory.java new file mode 100644 index 00000000000..7ce4f040f68 --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/ArenaOfGlory.java @@ -0,0 +1,117 @@ +package mage.cards.a; + +import mage.Mana; +import mage.abilities.common.EntersBattlefieldAbility; +import mage.abilities.common.delayed.ManaSpentDelayedTriggeredAbility; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.costs.common.ExertSourceCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.effects.common.AddContinuousEffectToGame; +import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; +import mage.abilities.effects.common.TapSourceEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.effects.mana.BasicManaEffect; +import mage.abilities.keyword.HasteAbility; +import mage.abilities.mana.RedManaAbility; +import mage.abilities.mana.SimpleManaAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.ComparisonType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.filter.FilterPermanent; +import mage.filter.StaticFilters; +import mage.filter.common.FilterControlledPermanent; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.stack.Spell; +import mage.target.targetpointer.FixedTarget; + +import java.util.UUID; + +/** + * @author Susucr + */ +public final class ArenaOfGlory extends CardImpl { + + private static final FilterPermanent filter = new FilterControlledPermanent(SubType.MOUNTAIN); + private static final Condition condition + = new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.EQUAL_TO, 0); + + public ArenaOfGlory(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); + + // Arena of Glory enters the battlefield tapped unless you control a Mountain. + this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect( + new TapSourceEffect(), condition + ), "tapped unless you control a Mountain")); + + // {T}: Add {R}. + this.addAbility(new RedManaAbility()); + + // {R}, {T}, Exert Arena of Glory: Add {R}{R}. If that mana is spent on a creature spell, it gains haste until end of turn. + SimpleManaAbility ability = new SimpleManaAbility( + new BasicManaEffect(Mana.RedMana(2)), + new ManaCostsImpl<>("{R}") + ); + ability.addEffect(new CreateDelayedTriggeredAbilityEffect( + new ArenaOfGloryDelayedTriggeredAbility() + )); + ability.addCost(new TapSourceCost()); + ability.addCost(new ExertSourceCost()); + this.addAbility(ability); + } + + private ArenaOfGlory(final ArenaOfGlory card) { + super(card); + } + + @Override + public ArenaOfGlory copy() { + return new ArenaOfGlory(this); + } +} + +class ArenaOfGloryDelayedTriggeredAbility extends ManaSpentDelayedTriggeredAbility { + + ArenaOfGloryDelayedTriggeredAbility() { + super( + new AddContinuousEffectToGame( + new GainAbilityTargetEffect( + HasteAbility.getInstance(), Duration.EndOfTurn, + "it gains haste until end of turn", true + ) + ), + StaticFilters.FILTER_SPELL_CREATURE + ); + this.usesStack = false; + this.triggerOnlyOnce = false; + setTriggerPhrase("If that mana is spent on a creature spell, "); + } + + private ArenaOfGloryDelayedTriggeredAbility(final ArenaOfGloryDelayedTriggeredAbility effect) { + super(effect); + } + + @Override + public ArenaOfGloryDelayedTriggeredAbility copy() { + return new ArenaOfGloryDelayedTriggeredAbility(this); + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (!super.checkTrigger(event, game)) { + return false; + } + Spell spell = game.getStack().getSpell(event.getTargetId()); + if (spell == null) { + return false; + } + getEffects().setTargetPointer(new FixedTarget(spell.getCard(), game)); + return true; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/ModernHorizons3.java b/Mage.Sets/src/mage/sets/ModernHorizons3.java index c38e7d5e135..7af5497041d 100644 --- a/Mage.Sets/src/mage/sets/ModernHorizons3.java +++ b/Mage.Sets/src/mage/sets/ModernHorizons3.java @@ -35,6 +35,7 @@ public final class ModernHorizons3 extends ExpansionSet { cards.add(new SetCardInfo("Annoyed Altisaur", 284, Rarity.UNCOMMON, mage.cards.a.AnnoyedAltisaur.class)); cards.add(new SetCardInfo("Arcbound Condor", 81, Rarity.UNCOMMON, mage.cards.a.ArcboundCondor.class)); cards.add(new SetCardInfo("Archway of Innovation", 214, Rarity.RARE, mage.cards.a.ArchwayOfInnovation.class)); + cards.add(new SetCardInfo("Arena of Glory", 215, Rarity.RARE, mage.cards.a.ArenaOfGlory.class)); cards.add(new SetCardInfo("Argent Dais", 20, Rarity.RARE, mage.cards.a.ArgentDais.class)); cards.add(new SetCardInfo("Arna Kennerud, Skycaptain", 178, Rarity.MYTHIC, mage.cards.a.ArnaKennerudSkycaptain.class)); cards.add(new SetCardInfo("Ashling, Flame Dancer", 115, Rarity.MYTHIC, mage.cards.a.AshlingFlameDancer.class)); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/mh3/ArenaOfGloryTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/mh3/ArenaOfGloryTest.java new file mode 100644 index 00000000000..920072526e1 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/mh3/ArenaOfGloryTest.java @@ -0,0 +1,69 @@ +package org.mage.test.cards.single.mh3; + +import mage.abilities.keyword.HasteAbility; +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * @author Susucr + */ +public class ArenaOfGloryTest extends CardTestPlayerBase { + + /** + * {@link mage.cards.a.ArenaOfGlory Arena of Glory} + * Land + * Arena of Glory enters the battlefield tapped unless you control a Mountain. + * {T}: Add {R}. + * {R}, {T}, Exert Arena of Glory: Add {R}{R}. If that mana is spent on a creature spell, it gains haste until end of turn. (An exerted permanent won’t untap during your next untap step.) + */ + private static final String arena = "Arena of Glory"; + + @Test + public void test_NormalManaNoHaste() { + setStrictChooseMode(true); + + addCard(Zone.HAND, playerA, "Dwarven Trader"); // vanilla for {R} + addCard(Zone.BATTLEFIELD, playerA, arena); + + castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Dwarven Trader", true); + checkAbility("Dwarven Trader doesn't have haste", 3, PhaseStep.PRECOMBAT_MAIN, playerA, "Dwarven Trader", HasteAbility.class, false); + + setStopAt(5, PhaseStep.BEGIN_COMBAT); + execute(); + + assertTapped(arena, false); + assertPermanentCount(playerA, "Dwarven Trader", 1); + assertAbility(playerA, "Dwarven Trader", HasteAbility.getInstance(), false); + } + + @Test + public void test_TwoCreatureHaste() { + setStrictChooseMode(true); + + addCard(Zone.HAND, playerA, "Dwarven Trader"); // vanilla for {R} + addCard(Zone.HAND, playerA, "Mons's Goblin Raiders"); // vanilla for {R} + addCard(Zone.BATTLEFIELD, playerA, arena); + addCard(Zone.BATTLEFIELD, playerA, "Mountain"); + + activateManaAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "{R}"); + castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Dwarven Trader", true); + castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Mons's Goblin Raiders", true); + checkAbility("Dwarven Trader has haste", 3, PhaseStep.PRECOMBAT_MAIN, playerA, "Dwarven Trader", HasteAbility.class, true); + checkAbility("Mons's Goblin Raiders has haste", 3, PhaseStep.PRECOMBAT_MAIN, playerA, "Mons's Goblin Raiders", HasteAbility.class, true); + + attack(3, playerA, "Dwarven Trader", playerB); + attack(3, playerA, "Mons's Goblin Raiders", playerB); + + setStopAt(5, PhaseStep.BEGIN_COMBAT); + execute(); + + assertTapped(arena, true); // exerted + assertLife(playerB, 20 - 2); + assertPermanentCount(playerA, "Dwarven Trader", 1); + assertAbility(playerA, "Dwarven Trader", HasteAbility.getInstance(), false); + assertPermanentCount(playerA, "Mons's Goblin Raiders", 1); + assertAbility(playerA, "Mons's Goblin Raiders", HasteAbility.getInstance(), false); + } +} diff --git a/Mage/src/main/java/mage/MageObjectReference.java b/Mage/src/main/java/mage/MageObjectReference.java index 17cb40cf71f..dd18a605c13 100644 --- a/Mage/src/main/java/mage/MageObjectReference.java +++ b/Mage/src/main/java/mage/MageObjectReference.java @@ -103,9 +103,10 @@ public class MageObjectReference implements Comparable, Ser } @Override - public String toString(){ - return "("+zoneChangeCounter+"|"+sourceId.toString().substring(0,3)+")"; + public String toString() { + return "(" + zoneChangeCounter + "|" + sourceId.toString().substring(0, 3) + ")"; } + public UUID getSourceId() { return sourceId; } @@ -185,6 +186,14 @@ public class MageObjectReference implements Comparable, Ser return null; } + public Spell getSpell(Game game) { + Spell spell = game.getSpell(sourceId); + if (spell != null && spell.getZoneChangeCounter(game) == zoneChangeCounter) { + return spell; + } + return null; + } + public boolean zoneCounterIsCurrent(Game game) { return game.getState().getZoneChangeCounter(sourceId) == zoneChangeCounter; } diff --git a/Mage/src/main/java/mage/abilities/common/delayed/ManaSpentDelayedTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/delayed/ManaSpentDelayedTriggeredAbility.java index 61a30721951..e43b58bf0ff 100644 --- a/Mage/src/main/java/mage/abilities/common/delayed/ManaSpentDelayedTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/delayed/ManaSpentDelayedTriggeredAbility.java @@ -27,7 +27,7 @@ public class ManaSpentDelayedTriggeredAbility extends DelayedTriggeredAbility { setTriggerPhrase("When you spend this mana to cast " + filter.getMessage() + ", "); } - private ManaSpentDelayedTriggeredAbility(final ManaSpentDelayedTriggeredAbility ability) { + protected ManaSpentDelayedTriggeredAbility(final ManaSpentDelayedTriggeredAbility ability) { super(ability); this.filter = ability.filter; } diff --git a/Mage/src/main/java/mage/abilities/effects/common/AddContinuousEffectToGame.java b/Mage/src/main/java/mage/abilities/effects/common/AddContinuousEffectToGame.java index 4b968b0b3c1..eeea16d1ade 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/AddContinuousEffectToGame.java +++ b/Mage/src/main/java/mage/abilities/effects/common/AddContinuousEffectToGame.java @@ -36,6 +36,7 @@ public class AddContinuousEffectToGame extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { for (Effect effect : this.effects) { + effect.setTargetPointer(this.getTargetPointer().copy()); game.addEffect((ContinuousEffect) effect, source); } return true;