diff --git a/Mage.Sets/src/mage/cards/p/PhyrexianTriniform.java b/Mage.Sets/src/mage/cards/p/PhyrexianTriniform.java new file mode 100644 index 0000000000..d0bc175183 --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/PhyrexianTriniform.java @@ -0,0 +1,43 @@ +package mage.cards.p; + +import mage.MageInt; +import mage.abilities.common.DiesSourceTriggeredAbility; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.keyword.EncoreAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.game.permanent.token.GolemToken; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class PhyrexianTriniform extends CardImpl { + + public PhyrexianTriniform(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{9}"); + + this.subtype.add(SubType.GOLEM); + this.power = new MageInt(9); + this.toughness = new MageInt(9); + + // When Phyrexian Triniform dies, create three 3/3 colorless Golem artifact creature tokens. + this.addAbility(new DiesSourceTriggeredAbility(new CreateTokenEffect(new GolemToken(), 3))); + + // Encore {12} + this.addAbility(new EncoreAbility(new GenericManaCost(12))); + } + + private PhyrexianTriniform(final PhyrexianTriniform card) { + super(card); + } + + @Override + public PhyrexianTriniform copy() { + return new PhyrexianTriniform(this); + } +} diff --git a/Mage.Sets/src/mage/sets/CommanderLegends.java b/Mage.Sets/src/mage/sets/CommanderLegends.java index 6c71b6b4f7..7c67ad067d 100644 --- a/Mage.Sets/src/mage/sets/CommanderLegends.java +++ b/Mage.Sets/src/mage/sets/CommanderLegends.java @@ -38,6 +38,7 @@ public final class CommanderLegends extends ExpansionSet { cards.add(new SetCardInfo("Mana Confluence", 721, Rarity.MYTHIC, mage.cards.m.ManaConfluence.class)); cards.add(new SetCardInfo("Mask of Memory", 324, Rarity.UNCOMMON, mage.cards.m.MaskOfMemory.class)); cards.add(new SetCardInfo("Mindless Automaton", 326, Rarity.UNCOMMON, mage.cards.m.MindlessAutomaton.class)); + cards.add(new SetCardInfo("Phyrexian Triniform", 331, Rarity.MYTHIC, mage.cards.p.PhyrexianTriniform.class)); cards.add(new SetCardInfo("Prossh, Skyraider of Kher", 530, Rarity.MYTHIC, mage.cards.p.ProsshSkyraiderOfKher.class)); cards.add(new SetCardInfo("Prying Eyes", 86, Rarity.COMMON, mage.cards.p.PryingEyes.class)); cards.add(new SetCardInfo("Rejuvenating Springs", 354, Rarity.RARE, mage.cards.r.RejuvenatingSprings.class)); diff --git a/Mage/src/main/java/mage/abilities/keyword/EncoreAbility.java b/Mage/src/main/java/mage/abilities/keyword/EncoreAbility.java new file mode 100644 index 0000000000..daa5ad597f --- /dev/null +++ b/Mage/src/main/java/mage/abilities/keyword/EncoreAbility.java @@ -0,0 +1,188 @@ +package mage.abilities.keyword; + +import mage.MageObjectReference; +import mage.abilities.Ability; +import mage.abilities.ActivatedAbilityImpl; +import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; +import mage.abilities.costs.Cost; +import mage.abilities.costs.common.ExileSourceFromGraveCost; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.RequirementEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.cards.Card; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.TimingRule; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.game.permanent.token.EmptyToken; +import mage.target.targetpointer.FixedTarget; +import mage.util.CardUtil; + +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; +import java.util.UUID; + +/** + * @author TheElk801 + */ +public class EncoreAbility extends ActivatedAbilityImpl { + + private final String rule; + + public EncoreAbility(Cost cost) { + super(Zone.GRAVEYARD, new EncoreEffect(), cost); + this.addCost(new ExileSourceFromGraveCost()); + this.timing = TimingRule.SORCERY; + this.rule = setRule(cost); + } + + public EncoreAbility(final EncoreAbility ability) { + super(ability); + this.rule = ability.rule; + } + + @Override + public EncoreAbility copy() { + return new EncoreAbility(this); + } + + @Override + public String getRule() { + return rule; + } + + private String setRule(Cost cost) { + return "Encore " + cost.getText() + " (" + cost.getText() + ", " + + "Exile this card from your graveyard: For each opponent, " + + "create a token copy that attacks that opponent this turn if able. " + + "They gain haste. Sacrifice them at the beginning of the next end step. " + + "Activate only as a sorcery)"; + } +} + +class EncoreEffect extends OneShotEffect { + + EncoreEffect() { + super(Outcome.PutCreatureInPlay); + } + + private EncoreEffect(final EncoreEffect effect) { + super(effect); + } + + @Override + public EncoreEffect copy() { + return new EncoreEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Card card = game.getCard(source.getSourceId()); + if (card == null) { + return false; + } + EmptyToken token = new EmptyToken(); + CardUtil.copyTo(token).from(card); + Set addedTokens = new HashSet<>(); + int opponentCount = game.getOpponents(source.getControllerId()).size(); + if (opponentCount < 1) { + return false; + } + token.putOntoBattlefield(opponentCount, game, source.getSourceId(), source.getControllerId()); + Iterator it = token.getLastAddedTokenIds().iterator(); + while (it.hasNext()) { + for (UUID playerId : game.getOpponents(source.getControllerId())) { + UUID tokenId = it.next(); + MageObjectReference mageObjectReference = new MageObjectReference(tokenId, game); + game.addEffect(new EncoreRequirementEffect( + mageObjectReference, playerId + ), source); + game.addEffect(new GainAbilityTargetEffect( + HasteAbility.getInstance(), Duration.Custom + ).setTargetPointer(new FixedTarget(mageObjectReference)), source); + addedTokens.add(mageObjectReference); + } + } + game.addDelayedTriggeredAbility(new AtTheBeginOfNextEndStepDelayedTriggeredAbility( + new EncoreSacrificeEffect(addedTokens) + ), source); + return true; + } +} + +class EncoreRequirementEffect extends RequirementEffect { + + private final MageObjectReference token; + private final UUID playerId; + + EncoreRequirementEffect(MageObjectReference token, UUID playerId) { + super(Duration.EndOfTurn); + this.token = token; + this.playerId = playerId; + } + + private EncoreRequirementEffect(final EncoreRequirementEffect effect) { + super(effect); + this.token = effect.token; + this.playerId = effect.playerId; + } + + @Override + public EncoreRequirementEffect copy() { + return new EncoreRequirementEffect(this); + } + + @Override + public boolean applies(Permanent permanent, Ability source, Game game) { + return token.refersTo(permanent, game); + } + + @Override + public UUID mustAttackDefender(Ability source, Game game) { + return playerId; + } + + @Override + public boolean mustAttack(Game game) { + return true; + } + + @Override + public boolean mustBlock(Game game) { + return false; + } +} + +class EncoreSacrificeEffect extends OneShotEffect { + + private final Set mageObjectReferenceSet = new HashSet<>(); + + EncoreSacrificeEffect(Set mageObjectReferenceSet) { + super(Outcome.Benefit); + this.mageObjectReferenceSet.addAll(mageObjectReferenceSet); + staticText = "sacrifice those tokens"; + } + + private EncoreSacrificeEffect(final EncoreSacrificeEffect effect) { + super(effect); + } + + @Override + public EncoreSacrificeEffect copy() { + return new EncoreSacrificeEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + for (MageObjectReference mageObjectReference : mageObjectReferenceSet) { + Permanent permanent = mageObjectReference.getPermanent(game); + if (permanent != null) { + permanent.sacrifice(source.getSourceId(), game); + } + } + return true; + } +} diff --git a/Utils/keywords.txt b/Utils/keywords.txt index 998e38e67a..ac4cda1909 100644 --- a/Utils/keywords.txt +++ b/Utils/keywords.txt @@ -27,6 +27,7 @@ Dredge|number| Echo|manaString| Embalm|cost, card| Enchant|type| +Encore|cost| Entwine|manaString| Eternalize|cost, card| Evoke|card, manaString|