diff --git a/Mage.Sets/src/mage/cards/q/Quasiduplicate.java b/Mage.Sets/src/mage/cards/q/Quasiduplicate.java new file mode 100644 index 00000000000..d8036653cf3 --- /dev/null +++ b/Mage.Sets/src/mage/cards/q/Quasiduplicate.java @@ -0,0 +1,36 @@ +package mage.cards.q; + +import java.util.UUID; +import mage.abilities.effects.common.CreateTokenCopyTargetEffect; +import mage.abilities.keyword.JumpStartAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.target.common.TargetControlledCreaturePermanent; + +/** + * + * @author TheElk801 + */ +public final class Quasiduplicate extends CardImpl { + + public Quasiduplicate(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{U}{U}"); + + // Create a token that's a copy of target creature you control. + this.getSpellAbility().addEffect(new CreateTokenCopyTargetEffect()); + this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); + + // Jump-start + this.addAbility(new JumpStartAbility(this)); + } + + public Quasiduplicate(final Quasiduplicate card) { + super(card); + } + + @Override + public Quasiduplicate copy() { + return new Quasiduplicate(this); + } +} diff --git a/Mage.Sets/src/mage/sets/GuildsOfRavnica.java b/Mage.Sets/src/mage/sets/GuildsOfRavnica.java index 9f15bb000fb..dfb39312d39 100644 --- a/Mage.Sets/src/mage/sets/GuildsOfRavnica.java +++ b/Mage.Sets/src/mage/sets/GuildsOfRavnica.java @@ -31,6 +31,7 @@ public final class GuildsOfRavnica extends ExpansionSet { cards.add(new SetCardInfo("Narcomoeba", 47, Rarity.RARE, mage.cards.n.Narcomoeba.class)); cards.add(new SetCardInfo("Necrotic Wound", 79, Rarity.UNCOMMON, mage.cards.n.NecroticWound.class)); cards.add(new SetCardInfo("Overgrown Tomb", 253, Rarity.RARE, mage.cards.o.OvergrownTomb.class)); + cards.add(new SetCardInfo("Quasiduplicate", 51, Rarity.RARE, mage.cards.q.Quasiduplicate.class)); cards.add(new SetCardInfo("Ral, Izzet Viceroy", 195, Rarity.MYTHIC, mage.cards.r.RalIzzetViceroy.class)); cards.add(new SetCardInfo("Sacred Foundry", 254, Rarity.RARE, mage.cards.s.SacredFoundry.class)); cards.add(new SetCardInfo("Sinister Sabotage", 54, Rarity.UNCOMMON, mage.cards.s.SinisterSabotage.class)); diff --git a/Mage/src/main/java/mage/abilities/keyword/JumpStartAbility.java b/Mage/src/main/java/mage/abilities/keyword/JumpStartAbility.java new file mode 100644 index 00000000000..5e829268059 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/keyword/JumpStartAbility.java @@ -0,0 +1,118 @@ +package mage.abilities.keyword; + +import mage.abilities.Ability; +import mage.abilities.SpellAbility; +import mage.abilities.costs.Cost; +import mage.abilities.costs.common.DiscardTargetCost; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.cards.Card; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.SpellAbilityType; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.ZoneChangeEvent; +import mage.players.Player; +import mage.target.common.TargetCardInHand; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author LevelX2 + */ +public class JumpStartAbility extends SpellAbility { + + public JumpStartAbility(Card card) { + super(card.getManaCost(), card.getName() + " with jump-start", Zone.GRAVEYARD, SpellAbilityType.BASE_ALTERNATE); + this.getCosts().addAll(card.getSpellAbility().getCosts().copy()); + Cost cost = new DiscardTargetCost(new TargetCardInHand()); + cost.setText(""); + this.addCost(cost); + this.getEffects().addAll(card.getSpellAbility().getEffects().copy()); + this.addEffect(new JumpStartReplacementEffect()); + this.getTargets().addAll(card.getSpellAbility().getTargets().copy()); + this.spellAbilityType = SpellAbilityType.BASE_ALTERNATE; + this.timing = card.getSpellAbility().getTiming(); + + } + + public JumpStartAbility(final JumpStartAbility ability) { + super(ability); + } + + @Override + public JumpStartAbility copy() { + return new JumpStartAbility(this); + } + + @Override + public String getRule(boolean all) { + return getRule(); + } + + @Override + public String getRule() { + return "Jump-start (You may cast this card from your graveyard " + + "by discarding a card in addition to paying its other costs. " + + "Then exile this card.)"; + } +} + +class JumpStartReplacementEffect extends ReplacementEffectImpl { + + public JumpStartReplacementEffect() { + super(Duration.OneUse, Outcome.Exile); + staticText = "(If this spell was cast with jump-start, " + + "exile it instead of putting it anywhere else " + + "any time it would leave the stack)"; + } + + public JumpStartReplacementEffect(final JumpStartReplacementEffect effect) { + super(effect); + } + + @Override + public JumpStartReplacementEffect copy() { + return new JumpStartReplacementEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + Card card = game.getCard(event.getTargetId()); + if (card != null) { + discard(); + return controller.moveCards( + card, Zone.EXILED, source, game, false, false, false, event.getAppliedEffects()); + } + } + return false; + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.ZONE_CHANGE; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + if (event.getTargetId().equals(source.getSourceId()) + && ((ZoneChangeEvent) event).getFromZone() == Zone.STACK + && ((ZoneChangeEvent) event).getToZone() != Zone.EXILED) { + + int zcc = game.getState().getZoneChangeCounter(source.getSourceId()); + if (((FixedTarget) getTargetPointer()).getZoneChangeCounter() + 1 == zcc) { + return true; + } + + } + return false; + } +} diff --git a/Utils/gen-card.pl b/Utils/gen-card.pl index 7a2646f1cb7..44abc4a54ce 100755 --- a/Utils/gen-card.pl +++ b/Utils/gen-card.pl @@ -242,6 +242,8 @@ foreach my $ability (@abilities) { $vars{'abilities'} .= "\n this.addAbility(" . $kw . "Ability.getInstance());"; } elsif ($keywords{$kw} eq 'new') { $vars{'abilities'} .= "\n this.addAbility(new " . $kw . "Ability());"; + } elsif ($keywords{$kw} eq 'card') { + $vars{'abilities'} .= "\n this.addAbility(new " . $kw . "Ability(this));"; } elsif ($keywords{$kw} eq 'color') { $vars{'abilities'} .= "\n this.addAbility(new " . $kw . "Ability(this.color));"; } elsif ($keywords{$kw} eq 'number') { diff --git a/Utils/keywords.txt b/Utils/keywords.txt index 0d080adf4cc..b965d6b3aea 100644 --- a/Utils/keywords.txt +++ b/Utils/keywords.txt @@ -51,7 +51,7 @@ Intimidate|instance| Ingest|new| Islandcycling|cost| Islandwalk|new| -Kick-start|card| +Jump-start|card| Level up|cost| Lifelink|instance| Living weapon|new|