Skip to content

[BLB] Implement Clement, the Worrywort #13444

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Apr 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 133 additions & 0 deletions Mage.Sets/src/mage/cards/c/ClementTheWorrywort.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
package mage.cards.c;

import mage.ConditionalMana;
import mage.MageInt;
import mage.Mana;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldThisOrAnotherTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.effects.common.ReturnToHandTargetEffect;
import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
import mage.abilities.keyword.VigilanceAbility;
import mage.abilities.mana.ConditionalColoredManaAbility;
import mage.abilities.mana.builder.ConditionalManaBuilder;
import mage.abilities.mana.conditional.CreatureCastManaCondition;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.filter.Filter;
import mage.filter.FilterPermanent;
import mage.filter.StaticFilters;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.mageobject.ManaValuePredicate;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.target.TargetPermanent;

import java.util.UUID;

/**
*
* @author earchip94
*/
public final class ClementTheWorrywort extends CardImpl {

private static final FilterPermanent frogFilter = new FilterPermanent(SubType.FROG, "Frogs");

public ClementTheWorrywort(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}{U}");

this.supertype.add(SuperType.LEGENDARY);
this.subtype.add(SubType.FROG);
this.subtype.add(SubType.DRUID);
this.power = new MageInt(3);
this.toughness = new MageInt(3);

// Vigilance
this.addAbility(VigilanceAbility.getInstance());

// Whenever Clement, the Worrywort or another creature you control enters, return up to one target creature you control with lesser mana value to its owner's hand.
this.addAbility(new ClementTheWorrywortTriggeredAbility());

// Frogs you control have "{T}: Add {G} or {U}. Spend this mana only to cast a creature spell."
Ability gMana = new ConditionalColoredManaAbility(new TapSourceCost(), Mana.GreenMana(1), new ClementTheWorrywortManaBuilder());
Ability bMana = new ConditionalColoredManaAbility(new TapSourceCost(), Mana.BlueMana(1), new ClementTheWorrywortManaBuilder());
Ability ability = new SimpleStaticAbility(
new GainAbilityControlledEffect(gMana, Duration.WhileOnBattlefield, frogFilter, false)
.setText("Frogs you control have \"{T}: Add {G} or {U}.")
);
ability.addEffect(
new GainAbilityControlledEffect(bMana, Duration.WhileOnBattlefield, frogFilter, false)
.setText("Spend this mana only to cast a creature spell.\"")
);
this.addAbility(ability);
}

private ClementTheWorrywort(final ClementTheWorrywort card) {
super(card);
}

@Override
public ClementTheWorrywort copy() {
return new ClementTheWorrywort(this);
}
}

class ClementTheWorrywortTriggeredAbility extends EntersBattlefieldThisOrAnotherTriggeredAbility {

ClementTheWorrywortTriggeredAbility() {
super(new ReturnToHandTargetEffect().setText("return up to one target creature you control with lesser mana value to its owner's hand"),
StaticFilters.FILTER_PERMANENT_CREATURE, false, true);
}

ClementTheWorrywortTriggeredAbility(final ClementTheWorrywortTriggeredAbility ability) {
super(ability);
}

@Override
public ClementTheWorrywortTriggeredAbility copy() {
return new ClementTheWorrywortTriggeredAbility(this);
}

@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (super.checkTrigger(event, game)) {
Permanent permanent = game.getPermanent(event.getTargetId());
if (permanent == null) {
return false;
}
int mv = permanent.getManaValue();
FilterControlledCreaturePermanent filter =
new FilterControlledCreaturePermanent("creature you control with mana value " + (mv - 1) + " or less");
filter.add(new ManaValuePredicate(ComparisonType.FEWER_THAN, mv));
this.addTarget(new TargetPermanent(0,1, filter));
return true;
}
return false;
}

}

class ClementTheWorrywortConditionalMana extends ConditionalMana {

ClementTheWorrywortConditionalMana(Mana mana) {
super(mana);
setComparisonScope(Filter.ComparisonScope.Any);
addCondition(new CreatureCastManaCondition());
}
}

class ClementTheWorrywortManaBuilder extends ConditionalManaBuilder {

@Override
public ConditionalMana build(Object... options) {
return new ClementTheWorrywortConditionalMana(this.mana);
}

@Override
public String getRule() {
return "Spend this mana only to cast a creature spell";
}
}
6 changes: 3 additions & 3 deletions Mage.Sets/src/mage/sets/Bloomburrow.java
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,9 @@ private Bloomburrow() {
cards.add(new SetCardInfo("Carrot Cake", 7, Rarity.COMMON, mage.cards.c.CarrotCake.class));
cards.add(new SetCardInfo("Charmed Sleep", 388, Rarity.COMMON, mage.cards.c.CharmedSleep.class));
cards.add(new SetCardInfo("Cindering Cutthroat", 208, Rarity.COMMON, mage.cards.c.CinderingCutthroat.class));
//cards.add(new SetCardInfo("Clement, the Worrywort", 209, Rarity.RARE, mage.cards.c.ClementTheWorrywort.class, NON_FULL_USE_VARIOUS));
//cards.add(new SetCardInfo("Clement, the Worrywort", 329, Rarity.RARE, mage.cards.c.ClementTheWorrywort.class, NON_FULL_USE_VARIOUS));
//cards.add(new SetCardInfo("Clement, the Worrywort", 347, Rarity.RARE, mage.cards.c.ClementTheWorrywort.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Clement, the Worrywort", 209, Rarity.RARE, mage.cards.c.ClementTheWorrywort.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Clement, the Worrywort", 329, Rarity.RARE, mage.cards.c.ClementTheWorrywort.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Clement, the Worrywort", 347, Rarity.RARE, mage.cards.c.ClementTheWorrywort.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Clifftop Lookout", 168, Rarity.UNCOMMON, mage.cards.c.ClifftopLookout.class));
cards.add(new SetCardInfo("Coiling Rebirth", 309, Rarity.RARE, mage.cards.c.CoilingRebirth.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Coiling Rebirth", 86, Rarity.RARE, mage.cards.c.CoilingRebirth.class, NON_FULL_USE_VARIOUS));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package org.mage.test.cards.abilities.enters;

import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;

import mage.constants.PhaseStep;
import mage.constants.Zone;

/**
*
* @author earchip94
*/
public class ClementTheWorrywortTest extends CardTestPlayerBase{

private final String frog = "Clement, the Worrywort";

@Test
public void castBounce() {
addCard(Zone.HAND, playerA, frog);
addCard(Zone.BATTLEFIELD, playerA, "Spore Frog");
addCard(Zone.BATTLEFIELD, playerA, "Forest");
addCard(Zone.BATTLEFIELD, playerA, "Island", 2);

castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, frog);
addTarget(playerA, "Spore Frog");

setStrictChooseMode(true);
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();

assertPermanentCount(playerA, 4);
assertHandCount(playerA, 1);
}

@Test
public void castNoTarget() {
addCard(Zone.HAND, playerA, frog);
addCard(Zone.BATTLEFIELD, playerA, "Haze Frog");
addCard(Zone.BATTLEFIELD, playerA, "Forest");
addCard(Zone.BATTLEFIELD, playerA, "Island", 2);

castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, frog);
setStrictChooseMode(false);

setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();

assertPermanentCount(playerA, 5);
assertHandCount(playerA, 0);
}

@Test
public void castOther() {
addCard(Zone.HAND, playerA, "Haze Frog");
addCard(Zone.BATTLEFIELD, playerA, frog);
addCard(Zone.BATTLEFIELD, playerA, "Forest", 5);

castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Haze Frog");
setChoice(playerA, "Whenever"); // order triggers
addTarget(playerA, frog);

setStrictChooseMode(true);
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();

assertPermanentCount(playerA, 6);
assertHandCount(playerA, 1);
}

@Test
public void castOtherNoTarget() {
addCard(Zone.HAND, playerA, "Spore Frog");
addCard(Zone.BATTLEFIELD, playerA, frog);
addCard(Zone.BATTLEFIELD, playerA, "Forest", 5);

castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Spore Frog");
setStrictChooseMode(false);

setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();

assertPermanentCount(playerA, 7);
assertHandCount(playerA, 0);
}

@Test
public void otherPlayerCast() {
addCard(Zone.BATTLEFIELD, playerA, frog);

addCard(Zone.HAND, playerB, "Llanowar Elves");
addCard(Zone.BATTLEFIELD, playerB, "Forest");

castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Llanowar Elves");
// No choice required

setStrictChooseMode(true);
setStopAt(2, PhaseStep.BEGIN_COMBAT);
execute();

assertPermanentCount(playerA, 1);
assertPermanentCount(playerB, 2);
assertChoicesCount(playerA, 0);
assertChoicesCount(playerB, 0);
}
}