From 83234762f621ec3725636c8ca56132f71f1f3712 Mon Sep 17 00:00:00 2001 From: Thomas Winwood Date: Fri, 12 Apr 2019 05:56:04 +0100 Subject: [PATCH] Implement Everythingamajig --- .../src/mage/cards/e/EverythingamajigB.java | 74 ++++++++ .../src/mage/cards/e/EverythingamajigC.java | 179 ++++++++++++++++++ .../src/mage/cards/e/EverythingamajigE.java | 148 +++++++++++++++ Mage.Sets/src/mage/sets/Unstable.java | 3 + .../java/mage/verify/VerifyCardDataTest.java | 1 + 5 files changed, 405 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/e/EverythingamajigB.java create mode 100644 Mage.Sets/src/mage/cards/e/EverythingamajigC.java create mode 100644 Mage.Sets/src/mage/cards/e/EverythingamajigE.java diff --git a/Mage.Sets/src/mage/cards/e/EverythingamajigB.java b/Mage.Sets/src/mage/cards/e/EverythingamajigB.java new file mode 100644 index 0000000000..4c87ca972a --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/EverythingamajigB.java @@ -0,0 +1,74 @@ + +package mage.cards.e; + +import java.util.UUID; + +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.condition.common.HellbentCondition; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.effects.common.PutCardFromHandOntoBattlefieldEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SuperType; +import mage.constants.Zone; +import mage.filter.common.FilterPermanentCard; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.NamePredicate; +import mage.filter.predicate.mageobject.SupertypePredicate; +import mage.filter.predicate.other.ExpansionSetPredicate; + +/** + * + * @author Ketsuban + */ +public final class EverythingamajigB extends CardImpl { + + private static final FilterPermanentCard filter = new FilterPermanentCard("a silver-bordered permanent card"); + + static { + filter.add(Predicates.and( + Predicates.not(new SupertypePredicate(SuperType.BASIC)), // all Un-set basic lands are black bordered cards, and thus illegal choices + Predicates.not(new NamePredicate("Steamflogger Boss")), // printed in Unstable with a black border + Predicates.or(new ExpansionSetPredicate("UGL"), new ExpansionSetPredicate("UNH"), new ExpansionSetPredicate("UST")) + )); + } + + public EverythingamajigB(UUID ownerId, CardSetInfo setInfo) { + super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{5}"); + + // Fool's Tome + // 2, T: Draw a card. Activate this ability only if you have no cards in hand. + Ability ability1 = new ConditionalActivatedAbility(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), new GenericManaCost(2), HellbentCondition.instance); + ability1.addCost(new TapSourceCost()); + this.addAbility(ability1); + + // Tower of Eons + // 8, T: You gain 10 life. + Ability ability2 = new SimpleActivatedAbility(Zone.BATTLEFIELD, new GainLifeEffect(10), new GenericManaCost(8)); + ability2.addCost(new TapSourceCost()); + this.addAbility(ability2); + + // Spatula of the Ages + // 4, T, Sacrifice Everythingamajig: You may put a silver-bordered permanent card from your hand onto the battlefield. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new PutCardFromHandOntoBattlefieldEffect(filter), new GenericManaCost(4)); + ability.addCost(new TapSourceCost()); + ability.addCost(new SacrificeSourceCost()); + this.addAbility(ability); + } + + public EverythingamajigB(final EverythingamajigB card) { + super(card); + } + + @Override + public EverythingamajigB copy() { + return new EverythingamajigB(this); + } +} diff --git a/Mage.Sets/src/mage/cards/e/EverythingamajigC.java b/Mage.Sets/src/mage/cards/e/EverythingamajigC.java new file mode 100644 index 0000000000..9868a33f90 --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/EverythingamajigC.java @@ -0,0 +1,179 @@ + +package mage.cards.e; + +import java.util.UUID; + +import mage.Mana; +import mage.abilities.Ability; +import mage.abilities.common.ActivateIfConditionActivatedAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.condition.common.MyTurnCondition; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.costs.mana.VariableManaCost; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.common.discard.DiscardTargetEffect; +import mage.abilities.effects.mana.BasicManaEffect; +import mage.abilities.mana.ActivatedManaAbilityImpl; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Layer; +import mage.constants.Outcome; +import mage.constants.SubLayer; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.TargetPlayer; + +/** + * + * @author Ketsuban + */ +public final class EverythingamajigC extends CardImpl { + + public EverythingamajigC(UUID ownerId, CardSetInfo setInfo) { + super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{5}"); + + // Mana Screw + // 1: Flip a coin. If you win the flip, add CC to your mana pool. Activate this ability only any time you could cast an instant. + this.addAbility(new ManaScrewAbility()); + + // Disrupting Scepter + // 3, T: Target player discards a card. Activate this ability only during your turn. + Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, new DiscardTargetEffect(1), new GenericManaCost(3), MyTurnCondition.instance); + ability.addTarget(new TargetPlayer()); + ability.addCost(new TapSourceCost()); + this.addAbility(ability); + + // Chimeric Staff + // X: Everythingamajig becomes an X/X Construct artifact creature until end of turn. + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new ChimericStaffEffect(), new VariableManaCost())); + } + + public EverythingamajigC(final EverythingamajigC card) { + super(card); + } + + @Override + public EverythingamajigC copy() { + return new EverythingamajigC(this); + } +} + +class ManaScrewAbility extends ActivatedManaAbilityImpl { + + public ManaScrewAbility() { + super(Zone.BATTLEFIELD, new ManaScrewEffect(), new GenericManaCost(1)); + this.netMana.add(new Mana(0, 0, 0, 0, 0, 2, 0, 0)); + } + + public ManaScrewAbility(final ManaScrewAbility ability) { + super(ability); + } + + @Override + public ActivationStatus canActivate(UUID playerId, Game game) { + Player player = game.getPlayer(playerId); + if (player != null && !player.isInPayManaMode()) { + return super.canActivate(playerId, game); + } + return ActivationStatus.getFalse(); + } + + @Override + public ManaScrewAbility copy() { + return new ManaScrewAbility(this); + } + + @Override + public String getRule() { + return super.getRule() + " Activate this ability only any time you could cast an instant."; + } +} + +class ManaScrewEffect extends BasicManaEffect { + + public ManaScrewEffect() { + super(Mana.ColorlessMana(2)); + this.staticText = "Flip a coin. If you win the flip, add {C}{C}"; + } + + public ManaScrewEffect(final ManaScrewEffect effect) { + super(effect); + this.manaTemplate = effect.manaTemplate.copy(); + } + + @Override + public ManaScrewEffect copy() { + return new ManaScrewEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player != null && player.flipCoin(source, game, true)) { + player.getManaPool().addMana(getMana(game, source), game, source); + } + return true; + } +} + +class ChimericStaffEffect extends ContinuousEffectImpl { + + public ChimericStaffEffect() { + super(Duration.EndOfTurn, Outcome.BecomeCreature); + setText(); + } + + public ChimericStaffEffect(final ChimericStaffEffect effect) { + super(effect); + } + + @Override + public ChimericStaffEffect copy() { + return new ChimericStaffEffect(this); + } + + @Override + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + Permanent permanent = game.getPermanent(source.getSourceId()); + if (permanent != null) { + switch (layer) { + case TypeChangingEffects_4: + if (sublayer == SubLayer.NA) { + permanent.addCardType(CardType.CREATURE); + permanent.getSubtype(game).add(SubType.CONSTRUCT); + } + break; + case PTChangingEffects_7: + if (sublayer == SubLayer.SetPT_7b) { + int xValue = source.getManaCostsToPay().getX(); + if (xValue != 0) { + permanent.getPower().setValue(xValue); + permanent.getToughness().setValue(xValue); + } + } + } + return true; + } + return false; + } + + @Override + public boolean apply(Game game, Ability source) { + return false; + } + + private void setText() { + staticText = duration.toString() + " {this} becomes an X/X Construct artifact creature"; + } + + @Override + public boolean hasLayer(Layer layer) { + return layer == Layer.PTChangingEffects_7 || layer == Layer.TypeChangingEffects_4; + } +} diff --git a/Mage.Sets/src/mage/cards/e/EverythingamajigE.java b/Mage.Sets/src/mage/cards/e/EverythingamajigE.java new file mode 100644 index 0000000000..439a921abd --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/EverythingamajigE.java @@ -0,0 +1,148 @@ + +package mage.cards.e; + +import java.util.UUID; + +import mage.MageObject; +import mage.Mana; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.Cost; +import mage.abilities.costs.common.DiscardTargetCost; +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect; +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.mana.SimpleManaAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.cards.SplitCard; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SpellAbilityType; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.filter.StaticFilters; +import mage.filter.predicate.Predicate; +import mage.game.Game; +import mage.game.stack.Spell; +import mage.target.common.TargetCardInHand; +import mage.target.common.TargetCardInLibrary; +import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.common.TargetControlledPermanent; + +/** + * + * @author Ketsuban + */ +public final class EverythingamajigE extends CardImpl { + + public EverythingamajigE(UUID ownerId, CardSetInfo setInfo) { + super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{5}"); + + // Zuran Orb + // Sacrifice a land: You gain 2 life. + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new GainLifeEffect(2), new SacrificeTargetCost(new TargetControlledPermanent(StaticFilters.FILTER_CONTROLLED_LAND_SHORT_TEXT)))); + + // Ashnod's Altar + // Sacrifice a creature: Add CC to your mana pool. + SacrificeTargetCost cost = new SacrificeTargetCost(new TargetControlledCreaturePermanent(StaticFilters.FILTER_CONTROLLED_CREATURE_SHORT_TEXT)); + this.addAbility(new SimpleManaAbility(Zone.BATTLEFIELD, Mana.ColorlessMana(2), cost)); + + // Urza's Hot Tub + // 2, Discard a card: Search your library for a card that shares a complete word in its name with the name of the discarded card, reveal it, put it into your hand, then shuffle your library. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new UrzasHotTubEffect(), new GenericManaCost(2)); + ability.addCost(new DiscardTargetCost(new TargetCardInHand())); + this.addAbility(ability); + } + + public EverythingamajigE(final EverythingamajigE card) { + super(card); + } + + @Override + public EverythingamajigE copy() { + return new EverythingamajigE(this); + } +} + +class UrzasHotTubEffect extends OneShotEffect { + + public UrzasHotTubEffect() { + super(Outcome.ReturnToHand); + this.staticText = "Search your library for a card that shares a complete word in its name with the discarded card, reveal it, put it into your hand, then shuffle your library"; + } + + public UrzasHotTubEffect(final UrzasHotTubEffect effect) { + super(effect); + } + + @Override + public UrzasHotTubEffect copy() { + return new UrzasHotTubEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + for (Cost cost : source.getCosts()) { + if (cost instanceof DiscardTargetCost) { + DiscardTargetCost discardCost = (DiscardTargetCost) cost; + Card discardedCard = discardCost.getCards().get(0); + if (discardedCard != null) { + FilterCard filter = new FilterCard(); + filter.add(new UrzasHotTubPredicate(discardedCard.getName())); + return new SearchLibraryPutInHandEffect(new TargetCardInLibrary(filter), true, true).apply(game, source); + } + } + } + return false; + } +} + +class UrzasHotTubPredicate implements Predicate { + + private final String referenceName; + + public UrzasHotTubPredicate(String referenceName) { + this.referenceName = referenceName; + } + + @Override + public boolean apply(MageObject input, Game game) { + String name = input.getName(); + if (input instanceof SplitCard) { + return sharesWordWithName(((SplitCard)input).getLeftHalfCard().getName()) || sharesWordWithName(((SplitCard)input).getRightHalfCard().getName()); + } else if (input instanceof Spell && ((Spell) input).getSpellAbility().getSpellAbilityType() == SpellAbilityType.SPLIT_FUSED){ + SplitCard card = (SplitCard) ((Spell)input).getCard(); + return sharesWordWithName(card.getLeftHalfCard().getName()) || sharesWordWithName(card.getRightHalfCard().getName()); + } else { + if (name.contains(" // ")) { + String leftName = name.substring(0, name.indexOf(" // ")); + String rightName = name.substring(name.indexOf(" // ") + 4, name.length()); + return sharesWordWithName(leftName) || sharesWordWithName(rightName); + } else { + return sharesWordWithName(name); + } + } + } + + private boolean sharesWordWithName(String str) { + if (referenceName == null || referenceName == "") { + return false; + } + String[] arr = referenceName.split("\\s+"); + for (int i = 0; i < arr.length; i++) { + if (str.contains(arr[i].replaceAll(",", ""))) { + return true; + } + } + return false; + } + + @Override + public String toString() { + return ""; + } +} diff --git a/Mage.Sets/src/mage/sets/Unstable.java b/Mage.Sets/src/mage/sets/Unstable.java index 393aee438e..5b874239b1 100644 --- a/Mage.Sets/src/mage/sets/Unstable.java +++ b/Mage.Sets/src/mage/sets/Unstable.java @@ -42,6 +42,9 @@ public final class Unstable extends ExpansionSet { cards.add(new SetCardInfo("Dr. Julius Jumblemorph", 130, Rarity.MYTHIC, mage.cards.d.DrJuliusJumblemorph.class)); cards.add(new SetCardInfo("Enraged Killbot", "145d", Rarity.COMMON, mage.cards.e.EnragedKillbot.class)); cards.add(new SetCardInfo("Earl of Squirrel", 108, Rarity.RARE, mage.cards.e.EarlOfSquirrel.class)); + cards.add(new SetCardInfo("Everythingamajig", "147b", Rarity.UNCOMMON, mage.cards.e.EverythingamajigB.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Everythingamajig", "147c", Rarity.UNCOMMON, mage.cards.e.EverythingamajigC.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Everythingamajig", "147e", Rarity.UNCOMMON, mage.cards.e.EverythingamajigE.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Forest", 216, Rarity.LAND, mage.cards.basiclands.Forest.class, new CardGraphicInfo(FrameStyle.UST_FULL_ART_BASIC, false))); cards.add(new SetCardInfo("GO TO JAIL", 8, Rarity.COMMON, mage.cards.g.GOTOJAIL.class)); cards.add(new SetCardInfo("Garbage Elemental", "82c", Rarity.UNCOMMON, mage.cards.g.GarbageElementalC.class, NON_FULL_USE_VARIOUS)); diff --git a/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java b/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java index 3e6594dbd1..dd17d6613d 100644 --- a/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java +++ b/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java @@ -194,6 +194,7 @@ public class VerifyCardDataTest { if (!needClass.equals(currentClass)) { // workaround to star wars and unstable set with same card names if (!checkCard.getName().equals("Syndicate Enforcer") + && !checkCard.getName().equals("Everythingamajig") && !checkCard.getName().equals("Garbage Elemental") && !checkCard.getName().equals("Very Cryptic Command")) { errorsList.add("Error: found wrong class in set " + set.getCode() + " - " + checkCard.getName() + " (" + currentClass + " <> " + needClass + ")");