diff --git a/Mage.Sets/src/mage/cards/j/JadeOrbOfDragonkind.java b/Mage.Sets/src/mage/cards/j/JadeOrbOfDragonkind.java new file mode 100644 index 00000000000..e8621343d43 --- /dev/null +++ b/Mage.Sets/src/mage/cards/j/JadeOrbOfDragonkind.java @@ -0,0 +1,139 @@ +package mage.cards.j; + +import mage.MageObjectReference; +import mage.abilities.Ability; +import mage.abilities.common.delayed.ManaSpentDelayedTriggeredAbility; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.HexproofAbility; +import mage.abilities.mana.BasicManaAbility; +import mage.abilities.mana.GreenManaAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.counters.CounterType; +import mage.filter.FilterSpell; +import mage.filter.common.FilterCreatureSpell; +import mage.game.Game; +import mage.game.events.EntersTheBattlefieldEvent; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.game.stack.Spell; + +import java.util.UUID; + +/** + * @author Zelane + */ +public final class JadeOrbOfDragonkind extends CardImpl { + + private static final FilterSpell filter = new FilterCreatureSpell("a Dragon creature spell"); + static { + filter.add(SubType.DRAGON.getPredicate()); + } + + public JadeOrbOfDragonkind(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[] { CardType.ARTIFACT }, "{2}{G}"); + + // {T}: Add {G}. When you spend this mana to cast a Dragon creature spell, it enters the battlefield with an additional +1/+1 counter on it and gains hexproof until your next turn. + BasicManaAbility ability = new GreenManaAbility(); + ManaSpentDelayedTriggeredAbility manaSpentAbility = new ManaSpentDelayedTriggeredAbility( + new JadeOrbAdditionalCounterEffect(), filter); + manaSpentAbility.addEffect(new JadeOrbGainHexproofEffect()); + ability.addEffect(new CreateDelayedTriggeredAbilityEffect(manaSpentAbility)); + ability.setUndoPossible(false); + this.addAbility(ability); + } + + private JadeOrbOfDragonkind(final JadeOrbOfDragonkind card) { + super(card); + } + + @Override + public JadeOrbOfDragonkind copy() { + return new JadeOrbOfDragonkind(this); + } +} + +class JadeOrbGainHexproofEffect extends GainAbilityTargetEffect { + + JadeOrbGainHexproofEffect() { + super(HexproofAbility.getInstance(), Duration.UntilYourNextTurn, null, true); + staticText = "and gains hexproof until your next turn"; + } + + private JadeOrbGainHexproofEffect(final JadeOrbGainHexproofEffect effect) { + super(effect); + } + + @Override + public JadeOrbGainHexproofEffect copy() { + return new JadeOrbGainHexproofEffect(this); + } + + @Override + public void init(Ability source, Game game) { + super.init(source, game); + + GameEvent event = ((ManaSpentDelayedTriggeredAbility) source).getTriggerEvent(); + if (event != null) { + Spell spell = game.getStack().getSpell(event.getTargetId()); + if (spell != null) { + affectedObjectList.add(new MageObjectReference(spell.getSourceId(), game)); + } + } + } +} + +class JadeOrbAdditionalCounterEffect extends ReplacementEffectImpl { + + JadeOrbAdditionalCounterEffect() { + super(Duration.EndOfTurn, Outcome.BoostCreature); + this.staticText = "it enters the battlefield with an additional +1/+1 counter on it"; + } + + private JadeOrbAdditionalCounterEffect(final JadeOrbAdditionalCounterEffect effect) { + super(effect); + } + + @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 (!(source instanceof ManaSpentDelayedTriggeredAbility)) { + return false; + } + GameEvent manaUsedEvent = ((ManaSpentDelayedTriggeredAbility) source).getTriggerEvent(); + Spell spell = game.getStack().getSpell(manaUsedEvent.getTargetId()); + if (spell == null) { + return false; + } + return event.getSourceId().equals(spell.getSourceId()); + } + + @Override + public boolean apply(Game game, Ability source) { + return false; + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + Permanent target = ((EntersTheBattlefieldEvent) event).getTarget(); + if (target != null) { + target.addCounters(CounterType.P1P1.createInstance(), source.getControllerId(), source, game, event.getAppliedEffects()); + } + return false; + } + + @Override + public JadeOrbAdditionalCounterEffect copy() { + return new JadeOrbAdditionalCounterEffect(this); + } +} diff --git a/Mage.Sets/src/mage/sets/CommanderLegendsBattleForBaldursGate.java b/Mage.Sets/src/mage/sets/CommanderLegendsBattleForBaldursGate.java index dbb7c2e3213..927a75016ca 100644 --- a/Mage.Sets/src/mage/sets/CommanderLegendsBattleForBaldursGate.java +++ b/Mage.Sets/src/mage/sets/CommanderLegendsBattleForBaldursGate.java @@ -327,6 +327,7 @@ public final class CommanderLegendsBattleForBaldursGate extends ExpansionSet { cards.add(new SetCardInfo("Izzet Boilerworks", 897, Rarity.UNCOMMON, mage.cards.i.IzzetBoilerworks.class)); cards.add(new SetCardInfo("Izzet Chemister", 798, Rarity.RARE, mage.cards.i.IzzetChemister.class)); cards.add(new SetCardInfo("Izzet Signet", 863, Rarity.COMMON, mage.cards.i.IzzetSignet.class)); + cards.add(new SetCardInfo("Jade Orb of Dragonkind", 236, Rarity.COMMON, mage.cards.j.JadeOrbOfDragonkind.class)); cards.add(new SetCardInfo("Jaheira's Respite", 238, Rarity.RARE, mage.cards.j.JaheirasRespite.class)); cards.add(new SetCardInfo("Jaheira, Friend of the Forest", 237, Rarity.RARE, mage.cards.j.JaheiraFriendOfTheForest.class)); cards.add(new SetCardInfo("Jan Jansen, Chaos Crafter", 277, Rarity.RARE, mage.cards.j.JanJansenChaosCrafter.class)); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/clb/JadeOrbOfDragonkindTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/clb/JadeOrbOfDragonkindTest.java new file mode 100644 index 00000000000..144dcd5eabf --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/clb/JadeOrbOfDragonkindTest.java @@ -0,0 +1,119 @@ +package org.mage.test.cards.single.clb; + +import mage.abilities.keyword.HexproofAbility; +import mage.constants.PhaseStep; +import mage.constants.Zone; +import mage.counters.CounterType; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * {@link mage.cards.j.JadeOrbOfDragonkind Jade Orb of Dragonkind} + * {2}{G} + * Artifact + * {T}: Add {G}. When you spend this mana to cast a Dragon creature spell, it enters the battlefield with an additional +1/+1 counter on it and gains hexproof until your next turn. + * @author NicolasCamachoP, Zelane + */ + +public class JadeOrbOfDragonkindTest extends CardTestPlayerBase { + private static final String jadeOrb = "Jade Orb of Dragonkind"; + private static final String arcades = "Arcades, the Strategist"; + private static final String mowu = "Mowu, Loyal Companion"; + + @Test + public void manaAbility() { + addCard(Zone.HAND, playerA, "Ancient Bronze Dragon"); + addCard(Zone.BATTLEFIELD, playerA, "Forest", 1); + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 5); + addCard(Zone.BATTLEFIELD, playerA, jadeOrb); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Ancient Bronze Dragon"); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertPermanentCount(playerA, 8); + assertTapped(jadeOrb, true); + } + + @Test + public void manaUsedEffects() { + addCard(Zone.HAND, playerA, arcades); + addCard(Zone.BATTLEFIELD, playerA, "Island", 2); + addCard(Zone.BATTLEFIELD, playerA, "Plains", 1); + addCard(Zone.BATTLEFIELD, playerA, jadeOrb); + addCard(Zone.BATTLEFIELD, playerA, "Kronch Wrangler"); + // Whenever a creature with power 4 or greater enters the battlefield under your control, put a +1/+1 counter on Kronch Wrangler. + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, arcades); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_COMBAT); + execute(); + + assertPermanentCount(playerA, 6); + assertTapped(jadeOrb, true); + assertCounterCount(arcades, CounterType.P1P1, 1); + assertPowerToughness(playerA, "Kronch Wrangler", 3, 2); + assertAbility(playerA, arcades, HexproofAbility.getInstance(), true); + } + + @Test + public void hexproofDropOff() { + addCard(Zone.HAND, playerA, arcades); + addCard(Zone.BATTLEFIELD, playerA, "Island", 2); + addCard(Zone.BATTLEFIELD, playerA, "Plains", 1); + addCard(Zone.BATTLEFIELD, playerA, jadeOrb); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, arcades); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_COMBAT); + execute(); + + assertPermanentCount(playerA, 5); + assertTapped(jadeOrb, true); + assertAbility(playerA, arcades, HexproofAbility.getInstance(), true); + + setStopAt(4, PhaseStep.UPKEEP); + execute(); + + assertAbility(playerA, arcades, HexproofAbility.getInstance(), false); + } + + @Test + public void twoOrbs() { + addCard(Zone.HAND, playerA, arcades); + addCard(Zone.BATTLEFIELD, playerA, "Island", 1); + addCard(Zone.BATTLEFIELD, playerA, "Plains", 1); + addCard(Zone.BATTLEFIELD, playerA, jadeOrb, 2); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, arcades); + //setChoice(playerA, "When you spend"); // order identical triggers + + setStrictChooseMode(false); // trigger order is problematic + setStopAt(1, PhaseStep.END_COMBAT); + execute(); + + assertPermanentCount(playerA, 5); + assertTapped(jadeOrb, true); + assertCounterCount(arcades, CounterType.P1P1, 2); + assertAbility(playerA, arcades, HexproofAbility.getInstance(), true); + } + + @Test + public void comboMowuAndMaskwoodNexus() { + addCard(Zone.HAND, playerA, mowu); + addCard(Zone.BATTLEFIELD, playerA, "Maskwood Nexus", 1); + addCard(Zone.BATTLEFIELD, playerA, "Forest", 2); + addCard(Zone.BATTLEFIELD, playerA, "Plains", 1); + addCard(Zone.BATTLEFIELD, playerA, jadeOrb); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, mowu); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_COMBAT); + execute(); + + assertTapped(jadeOrb, true); + assertCounterCount(mowu, CounterType.P1P1, 2); + assertAbility(playerA, mowu, HexproofAbility.getInstance(), true); + } +}