Implement [LEG] Takklemaggot

This commit is contained in:
xenohedron 2023-10-18 00:30:46 -04:00
parent 1c19280693
commit 833d209795
5 changed files with 284 additions and 0 deletions

View file

@ -0,0 +1,231 @@
package mage.cards.t;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.common.DiesAttachedTriggeredAbility;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.effects.common.counter.AddCountersAttachedEffect;
import mage.abilities.keyword.EnchantAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.counters.CounterType;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.permanent.CanBeEnchantedByPredicate;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.Target;
import mage.target.TargetPermanent;
import mage.target.common.TargetCreaturePermanent;
import mage.target.targetpointer.FixedTarget;
import mage.util.CardUtil;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
/**
* @author xenohedron
*/
public final class Takklemaggot extends CardImpl {
public Takklemaggot(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{B}{B}");
this.subtype.add(SubType.AURA);
// Enchant creature
TargetPermanent auraTarget = new TargetCreaturePermanent();
this.getSpellAbility().addTarget(auraTarget);
this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature));
this.addAbility(new EnchantAbility(auraTarget));
// At the beginning of the upkeep of enchanted creature's controller, put a -0/-1 counter on that creature.
this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD,
new AddCountersAttachedEffect(CounterType.M0M1.createInstance(), "that creature"),
TargetController.CONTROLLER_ATTACHED_TO, false, false));
// When enchanted creature dies, that creature's controller chooses a creature that Takklemaggot could enchant.
// If they do, return Takklemaggot to the battlefield under your control attached to that creature.
// If they don't, return Takklemaggot to the battlefield under your control as a non-Aura enchantment.
// It loses "enchant creature" and gains "At the beginning of that player's upkeep, Takklemaggot deals 1 damage to that player."
this.addAbility(new DiesAttachedTriggeredAbility(new TakklemaggotEffect(), "enchanted creature",
false, true, SetTargetPointer.ATTACHED_TO_CONTROLLER));
}
private Takklemaggot(final Takklemaggot card) {
super(card);
}
@Override
public Takklemaggot copy() {
return new Takklemaggot(this);
}
}
class TakklemaggotEffect extends OneShotEffect {
TakklemaggotEffect() {
super(Outcome.PutCardInPlay);
staticText = "that creature's controller chooses a creature that {this} could enchant. " +
"If the player does, return {this} to the battlefield under your control attached to that creature. " +
"If they don't, return {this} to the battlefield under your control as a non-Aura enchantment. " +
"It loses \"enchant creature\" and gains \"At the beginning of that player's upkeep, {this} deals 1 damage to that player.\"";
}
private TakklemaggotEffect(final TakklemaggotEffect effect) {
super(effect);
}
@Override
public TakklemaggotEffect copy() {
return new TakklemaggotEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Player player = game.getPlayer(getTargetPointer().getFirst(game, source));
Card auraCard = game.getCard(source.getSourceId());
if (controller == null || player == null || auraCard == null) {
return false;
}
FilterCreaturePermanent filter = new FilterCreaturePermanent();
filter.add(new CanBeEnchantedByPredicate(auraCard));
Target target = new TargetCreaturePermanent(filter).withNotTarget(true);
if (!game.getBattlefield().getActivePermanents(filter, player.getId(), source, game).isEmpty()
&& player.choose(outcome, target, source, game)) {
// return attached to that creature
Permanent creature = game.getPermanent(target.getFirstTarget());
if (creature == null) {
return false;
}
game.getState().setValue("attachTo:" + auraCard.getId(), creature);
controller.moveCards(auraCard, Zone.BATTLEFIELD, source, game);
creature.addAttachment(auraCard.getId(), source, game);
} else {
// return as non-Aura enchantment
game.addEffect(new TakklemaggotNonAuraEffect(player.getId()), source);
controller.moveCards(auraCard, Zone.BATTLEFIELD, source, game);
auraCard.addInfo("chosen player", CardUtil.addToolTipMarkTags("Chosen player: " + player.getLogName()), game);
}
return true;
}
}
class TakklemaggotNonAuraEffect extends ContinuousEffectImpl {
private final UUID playerId;
TakklemaggotNonAuraEffect(UUID playerId) {
super(Duration.Custom, Outcome.AddAbility);
this.playerId = playerId;
}
private TakklemaggotNonAuraEffect(final TakklemaggotNonAuraEffect effect) {
super(effect);
this.playerId = effect.playerId;
}
@Override
public TakklemaggotNonAuraEffect copy() {
return new TakklemaggotNonAuraEffect(this);
}
@Override
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
Permanent permanent;
if (affectedObjectList.isEmpty()) { // not yet initiated, check entering permanent
permanent = game.getPermanentEntering(source.getSourceId());
// if an entering permanent is found, then proceed to applying continuous effects by layer
// otherwise try to find the permanent on the battlefield
if (permanent == null) {
permanent = game.getPermanent(source.getSourceId());
if (permanent == null) {
discard(); // no permanent found, can't initiate
return false;
} else {
// initiate with ZCC and check that in all future calls
affectedObjectList.add(new MageObjectReference(source.getSourceId(), game));
}
}
} else {
permanent = affectedObjectList.get(0).getPermanent(game);
if (permanent == null) {
discard(); // permanent no longer on battlefield so effect no longer applies
return true;
}
}
switch (layer) {
case TypeChangingEffects_4:
permanent.removeSubType(game, SubType.AURA);
return true;
case AbilityAddingRemovingEffects_6:
List<Ability> toRemove = new ArrayList<>();
for (Ability ability : permanent.getAbilities(game)) {
if (ability instanceof EnchantAbility) {
toRemove.add(ability);
}
}
permanent.removeAbilities(toRemove, source.getSourceId(), game);
permanent.addAbility(new TakklemaggotUpkeepAbility(playerId), source.getSourceId(), game);
return true;
default:
return true;
}
}
@Override
public boolean apply(Game game, Ability source) {
return false;
}
@Override
public boolean hasLayer(Layer layer) {
return Layer.AbilityAddingRemovingEffects_6 == layer || Layer.TypeChangingEffects_4 == layer;
}
}
class TakklemaggotUpkeepAbility extends TriggeredAbilityImpl {
private final UUID playerId;
TakklemaggotUpkeepAbility(UUID playerId) {
super(Zone.BATTLEFIELD, new DamageTargetEffect(1, true, "that player")
.setTargetPointer(new FixedTarget(playerId)), false);
this.playerId = playerId;
setTriggerPhrase("At the beginning of that player's upkeep, ");
}
private TakklemaggotUpkeepAbility(final TakklemaggotUpkeepAbility ability) {
super(ability);
this.playerId = ability.playerId;
}
@Override
public TakklemaggotUpkeepAbility copy() {
return new TakklemaggotUpkeepAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.UPKEEP_STEP_PRE;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
return event.getPlayerId().equals(this.playerId);
}
}

View file

@ -118,6 +118,7 @@ public final class Chronicles extends ExpansionSet {
cards.add(new SetCardInfo("Sol'kanar the Swamp King", 85, Rarity.RARE, mage.cards.s.SolkanarTheSwampKing.class));
cards.add(new SetCardInfo("Stangg", 86, Rarity.RARE, mage.cards.s.Stangg.class));
cards.add(new SetCardInfo("Storm Seeker", 70, Rarity.UNCOMMON, mage.cards.s.StormSeeker.class));
cards.add(new SetCardInfo("Takklemaggot", 37, Rarity.UNCOMMON, mage.cards.t.Takklemaggot.class));
cards.add(new SetCardInfo("Teleport", 26, Rarity.RARE, mage.cards.t.Teleport.class));
cards.add(new SetCardInfo("The Fallen", 38, Rarity.UNCOMMON, mage.cards.t.TheFallen.class));
cards.add(new SetCardInfo("The Wretched", 39, Rarity.RARE, mage.cards.t.TheWretched.class));

View file

@ -273,6 +273,7 @@ public final class Legends extends ExpansionSet {
cards.add(new SetCardInfo("Sylvan Library", 207, Rarity.UNCOMMON, mage.cards.s.SylvanLibrary.class));
cards.add(new SetCardInfo("Sylvan Paradise", 208, Rarity.UNCOMMON, mage.cards.s.SylvanParadise.class));
cards.add(new SetCardInfo("Syphon Soul", 118, Rarity.COMMON, mage.cards.s.SyphonSoul.class));
cards.add(new SetCardInfo("Takklemaggot", 119, Rarity.UNCOMMON, mage.cards.t.Takklemaggot.class));
cards.add(new SetCardInfo("Telekinesis", 79, Rarity.RARE, mage.cards.t.Telekinesis.class));
cards.add(new SetCardInfo("Teleport", 80, Rarity.RARE, mage.cards.t.Teleport.class));
cards.add(new SetCardInfo("Tetsuo Umezawa", 262, Rarity.RARE, mage.cards.t.TetsuoUmezawa.class));

View file

@ -218,6 +218,7 @@ public final class MastersEditionIII extends ExpansionSet {
cards.add(new SetCardInfo("Swamp", 223, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Swamp", 224, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Sword of the Ages", 202, Rarity.RARE, mage.cards.s.SwordOfTheAges.class));
cards.add(new SetCardInfo("Takklemaggot", 76, Rarity.UNCOMMON, mage.cards.t.Takklemaggot.class));
cards.add(new SetCardInfo("Tetsuo Umezawa", 179, Rarity.RARE, mage.cards.t.TetsuoUmezawa.class));
cards.add(new SetCardInfo("The Abyss", 77, Rarity.RARE, mage.cards.t.TheAbyss.class));
cards.add(new SetCardInfo("The Lady of the Mountain", 180, Rarity.COMMON, mage.cards.t.TheLadyOfTheMountain.class));

View file

@ -0,0 +1,50 @@
package org.mage.test.cards.single.leg;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import mage.counters.CounterType;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
public class TakklemaggotTest extends CardTestPlayerBase {
private static final String takklemaggot = "Takklemaggot"; // 2BB Aura
/* Enchant creature
At the beginning of the upkeep of enchanted creatures controller, put a -0/-1 counter on that creature.
When enchanted creature dies, that creatures controller chooses a creature that Takklemaggot could enchant.
If the player does, return Takklemaggot to the battlefield under your control attached to that creature.
If they dont, return Takklemaggot to the battlefield under your control as a non-Aura enchantment.
It loses enchant creature and gains At the beginning of that players upkeep, Takklemaggot deals 1 damage to that player.
*/
@Test
public void testTakklemaggot() {
addCard(Zone.HAND, playerA, takklemaggot, 1);
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 4);
addCard(Zone.BATTLEFIELD, playerB, "Harvest Hand", 1); // 2/2 returns as equipment "Scrounged Scythe"
addCard(Zone.BATTLEFIELD, playerB, "White Knight", 1); // 2/2 protection from black
addCard(Zone.BATTLEFIELD, playerB, "Mist Leopard", 1); // 3/2 shroud
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, takklemaggot, "Harvest Hand");
checkPT("t1", 1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Harvest Hand", 2,2);
checkPT("t2", 2, PhaseStep.PRECOMBAT_MAIN, playerB, "Harvest Hand", 2, 1);
checkPT("t3", 3, PhaseStep.PRECOMBAT_MAIN, playerB, "Harvest Hand", 2, 1);
setChoice(playerB, "Mist Leopard");
checkPermanentCount("equipment", 4, PhaseStep.POSTCOMBAT_MAIN, playerB, "Scrounged Scythe", 1);
checkPermanentCount("takklemaggot", 4, PhaseStep.POSTCOMBAT_MAIN, playerA, takklemaggot, 1);
checkPT("t5", 5, PhaseStep.PRECOMBAT_MAIN, playerB, "Mist Leopard", 3, 2);
checkPT("t6", 6, PhaseStep.PRECOMBAT_MAIN, playerB, "Mist Leopard", 3, 1);
checkPT("t7", 7, PhaseStep.PRECOMBAT_MAIN, playerB, "Mist Leopard", 3, 1);
checkGraveyardCount("leopard", 8, PhaseStep.POSTCOMBAT_MAIN, playerB, "Mist Leopard", 1);
checkLife("t9", 9, PhaseStep.PRECOMBAT_MAIN, playerB, 20);
checkLife("t10", 10, PhaseStep.PRECOMBAT_MAIN, playerB, 19);
checkLife("t11", 11, PhaseStep.PRECOMBAT_MAIN, playerB, 19);
setStopAt(12, PhaseStep.POSTCOMBAT_MAIN);
setStrictChooseMode(true);
execute();
assertLife(playerB, 18);
}
}