From c600bfcd6bec012c85fbe8c06069f7f0fa59247e Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Mon, 6 Jun 2022 19:04:52 -0400 Subject: [PATCH] [CLB] Implemented Myrkul, Lord of Bones --- .../src/mage/cards/m/MyrkulLordOfBones.java | 113 ++++++++++++++++++ .../CommanderLegendsBattleForBaldursGate.java | 1 + .../common/CreateTokenCopyTargetEffect.java | 19 ++- 3 files changed, 131 insertions(+), 2 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/m/MyrkulLordOfBones.java diff --git a/Mage.Sets/src/mage/cards/m/MyrkulLordOfBones.java b/Mage.Sets/src/mage/cards/m/MyrkulLordOfBones.java new file mode 100644 index 00000000000..a496ee97c9a --- /dev/null +++ b/Mage.Sets/src/mage/cards/m/MyrkulLordOfBones.java @@ -0,0 +1,113 @@ +package mage.cards.m; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.DiesCreatureTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.Condition; +import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateTokenCopyTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.abilities.keyword.IndestructibleAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.filter.predicate.permanent.TokenPredicate; +import mage.game.Game; +import mage.game.permanent.PermanentCard; +import mage.players.Player; + +import java.util.Objects; +import java.util.Optional; +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class MyrkulLordOfBones extends CardImpl { + + private static final FilterPermanent filter + = new FilterControlledCreaturePermanent("another nontoken creature you control"); + + static { + filter.add(AnotherPredicate.instance); + filter.add(TokenPredicate.FALSE); + } + + public MyrkulLordOfBones(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{W}{B}{G}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.GOD); + this.power = new MageInt(7); + this.toughness = new MageInt(5); + + // As long as your life total is less than or equal to half your starting life total, Myrkul, Lord of Bones has indestructible. + this.addAbility(new SimpleStaticAbility(new ConditionalContinuousEffect(new GainAbilitySourceEffect(IndestructibleAbility.getInstance()), MyrkulLordOfBonesCondition.instance, "as long as your life total is less than or equal to half your starting life total, {this} has indestructible"))); + + // Whenever another nontoken creature you control dies, you may exile it. If you do, create a token that's a copy of that card, except it's an enchantment and loses all other card types. + this.addAbility(new DiesCreatureTriggeredAbility(new MyrkulLordOfBonesEffect(), true, filter, true)); + } + + private MyrkulLordOfBones(final MyrkulLordOfBones card) { + super(card); + } + + @Override + public MyrkulLordOfBones copy() { + return new MyrkulLordOfBones(this); + } +} + +enum MyrkulLordOfBonesCondition implements Condition { + instance; + + @Override + public boolean apply(Game game, Ability source) { + return Optional.of(game.getPlayer(source.getControllerId())) + .filter(Objects::nonNull) + .map(Player::getLife) + .map(x -> 2 * x >= game.getStartingLife()) + .orElse(false); + } +} + +class MyrkulLordOfBonesEffect extends OneShotEffect { + + MyrkulLordOfBonesEffect() { + super(Outcome.Benefit); + staticText = "exile it. If you do, create a token that's a copy of that card, " + + "except it's an enchantment and loses all other card types"; + } + + private MyrkulLordOfBonesEffect(final MyrkulLordOfBonesEffect effect) { + super(effect); + } + + @Override + public MyrkulLordOfBonesEffect copy() { + return new MyrkulLordOfBonesEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + Card card = game.getCard(getTargetPointer().getFirst(game, source)); + if (player == null || card == null) { + return false; + } + player.moveCards(card, Zone.EXILED, source, game); + return new CreateTokenCopyTargetEffect().setSavedPermanent( + new PermanentCard(card, source.getControllerId(), game) + ).setPermanentModifier((token, g) -> { + token.getCardType().clear(); + token.addCardType(CardType.ENCHANTMENT); + token.retainAllEnchantmentSubTypes(null); + }).apply(game, source); + } +} diff --git a/Mage.Sets/src/mage/sets/CommanderLegendsBattleForBaldursGate.java b/Mage.Sets/src/mage/sets/CommanderLegendsBattleForBaldursGate.java index 92644a4148d..4d2fef27d0d 100644 --- a/Mage.Sets/src/mage/sets/CommanderLegendsBattleForBaldursGate.java +++ b/Mage.Sets/src/mage/sets/CommanderLegendsBattleForBaldursGate.java @@ -393,6 +393,7 @@ public final class CommanderLegendsBattleForBaldursGate extends ExpansionSet { cards.add(new SetCardInfo("Myriad Landscape", 904, Rarity.UNCOMMON, mage.cards.m.MyriadLandscape.class)); cards.add(new SetCardInfo("Myrkul's Edict", 135, Rarity.COMMON, mage.cards.m.MyrkulsEdict.class)); cards.add(new SetCardInfo("Myrkul's Invoker", 136, Rarity.COMMON, mage.cards.m.MyrkulsInvoker.class)); + cards.add(new SetCardInfo("Myrkul, Lord of Bones", 287, Rarity.RARE, mage.cards.m.MyrkulLordOfBones.class)); cards.add(new SetCardInfo("Mystery Key", 85, Rarity.UNCOMMON, mage.cards.m.MysteryKey.class)); cards.add(new SetCardInfo("Nalia de'Arnise", 649, Rarity.MYTHIC, mage.cards.n.NaliaDeArnise.class)); cards.add(new SetCardInfo("Natural Reclamation", 829, Rarity.COMMON, mage.cards.n.NaturalReclamation.class)); diff --git a/Mage/src/main/java/mage/abilities/effects/common/CreateTokenCopyTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/CreateTokenCopyTargetEffect.java index 103b596e4b1..a115c75b64d 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/CreateTokenCopyTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/CreateTokenCopyTargetEffect.java @@ -18,6 +18,7 @@ import mage.counters.CounterType; import mage.game.Game; import mage.game.permanent.Permanent; import mage.game.permanent.token.EmptyToken; +import mage.game.permanent.token.Token; import mage.target.targetpointer.FixedTarget; import mage.target.targetpointer.FixedTargets; import mage.util.CardUtil; @@ -31,6 +32,11 @@ import java.util.*; */ public class CreateTokenCopyTargetEffect extends OneShotEffect { + @FunctionalInterface + public interface PermanentModifier { + void apply(Token token, Game game); + } + private final Set> abilityClazzesToRemove; private final List addedTokenPermanents; private final List additionalAbilities; @@ -54,7 +60,7 @@ public class CreateTokenCopyTargetEffect extends OneShotEffect { private final int tokenPower; private final int tokenToughness; private boolean useLKI = false; - + private PermanentModifier permanentModifier = null; public CreateTokenCopyTargetEffect(boolean useLKI) { this(); @@ -235,6 +241,9 @@ public class CreateTokenCopyTargetEffect extends OneShotEffect { token.getColor().setColor(color); } additionalAbilities.stream().forEach(token::addAbility); + if (permanentModifier != null) { + permanentModifier.apply(token, game); + } if (!this.abilityClazzesToRemove.isEmpty()) { List abilitiesToRemoveTmp = new ArrayList<>(); @@ -364,7 +373,8 @@ public class CreateTokenCopyTargetEffect extends OneShotEffect { } public CreateTokenCopyTargetEffect addAbilityClassesToRemoveFromTokens(Class clazz) { - this.abilityClazzesToRemove.add(clazz);return this; + this.abilityClazzesToRemove.add(clazz); + return this; } public CreateTokenCopyTargetEffect addAdditionalAbilities(Ability... abilities) { @@ -378,6 +388,11 @@ public class CreateTokenCopyTargetEffect extends OneShotEffect { return this; } + public CreateTokenCopyTargetEffect setPermanentModifier(PermanentModifier permanentModifier) { + this.permanentModifier = permanentModifier; + return this; + } + public void sacrificeTokensCreatedAtNextEndStep(Game game, Ability source) { this.removeTokensCreatedAtEndOf(game, source, PhaseStep.END_TURN, false); }