[CLB] Implemented Jade Orb of Dragonkind (#10286)

* Working with oneshot

* Swap to dual effects

* adjust tests

* adjust custom class names, fix text order

* comparison fix, null check, access modifiers

---------

Co-authored-by: Zelane <zelane@hollow.tech>
Co-authored-by: xenohedron <xenohedron@users.noreply.github.com>
This commit is contained in:
Matt M 2023-08-12 23:25:46 +01:00 committed by GitHub
parent 23cc483a09
commit e49020e490
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 259 additions and 0 deletions

View file

@ -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);
}
}

View file

@ -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));

View file

@ -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);
}
}