diff --git a/Mage.Sets/src/mage/cards/s/ShinryuTranscendentRival.java b/Mage.Sets/src/mage/cards/s/ShinryuTranscendentRival.java new file mode 100644 index 00000000000..ba687c76ebc --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/ShinryuTranscendentRival.java @@ -0,0 +1,134 @@ +package mage.cards.s; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.abilities.effects.common.WinGameSourceControllerEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.TargetPlayer; +import mage.target.common.TargetOpponent; + +import java.util.Optional; +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class ShinryuTranscendentRival extends CardImpl { + + public ShinryuTranscendentRival(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, ""); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.DRAGON); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + this.color.setBlack(true); + this.nightCard = true; + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // As this creature transforms into Shinryu, choose an opponent. + this.addAbility(new SimpleStaticAbility(new ShinryuTranscendentRivalEffect())); + + // Burning Chains -- When the chosen player loses the game, you win the game. + this.addAbility(new ShinryuTranscendentRivalTriggeredAbility()); + } + + private ShinryuTranscendentRival(final ShinryuTranscendentRival card) { + super(card); + } + + @Override + public ShinryuTranscendentRival copy() { + return new ShinryuTranscendentRival(this); + } +} + +class ShinryuTranscendentRivalEffect extends ReplacementEffectImpl { + + ShinryuTranscendentRivalEffect() { + super(Duration.WhileOnBattlefield, Outcome.Benefit); + staticText = "as this creature transforms into {this}, choose an opponent"; + } + + private ShinryuTranscendentRivalEffect(final ShinryuTranscendentRivalEffect effect) { + super(effect); + } + + @Override + public ShinryuTranscendentRivalEffect copy() { + return new ShinryuTranscendentRivalEffect(this); + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + Player controller = game.getPlayer(source.getControllerId()); + Permanent permanent = game.getPermanent(source.getSourceId()); + if (controller == null || permanent == null) { + return false; + } + TargetPlayer target = new TargetOpponent(true); + controller.choose(outcome, target, source, game); + Player opponent = game.getPlayer(target.getFirstTarget()); + if (opponent == null) { + return false; + } + game.informPlayers(permanent.getName() + ": " + controller.getLogName() + " has chosen " + opponent.getLogName()); + game.getState().setValue(permanent.getId() + "_" + permanent.getZoneChangeCounter(game) + "_opponent", opponent.getId()); + return false; + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.TRANSFORMING; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + return source.getSourceId().equals(event.getTargetId()) + && source.getSourcePermanentIfItStillExists(game) != null; + } +} + +class ShinryuTranscendentRivalTriggeredAbility extends TriggeredAbilityImpl { + + ShinryuTranscendentRivalTriggeredAbility() { + super(Zone.BATTLEFIELD, new WinGameSourceControllerEffect()); + this.setTriggerPhrase("When the chosen player loses the game, "); + this.withFlavorWord("Burning Chains"); + } + + private ShinryuTranscendentRivalTriggeredAbility(final ShinryuTranscendentRivalTriggeredAbility ability) { + super(ability); + } + + @Override + public ShinryuTranscendentRivalTriggeredAbility copy() { + return new ShinryuTranscendentRivalTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.LOSES; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + return Optional + .ofNullable(this.getId() + "_" + this.getSourceObjectZoneChangeCounter() + "_opponent") + .map(game.getState()::getValue) + .map(event.getPlayerId()::equals) + .orElse(false); + } +} diff --git a/Mage.Sets/src/mage/cards/z/ZenosYaeGalvus.java b/Mage.Sets/src/mage/cards/z/ZenosYaeGalvus.java new file mode 100644 index 00000000000..5db0ae321ec --- /dev/null +++ b/Mage.Sets/src/mage/cards/z/ZenosYaeGalvus.java @@ -0,0 +1,102 @@ +package mage.cards.z; + +import mage.MageInt; +import mage.MageObjectReference; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.LeavesBattlefieldAllTriggeredAbility; +import mage.abilities.effects.common.ChooseCreatureEffect; +import mage.abilities.effects.common.TransformSourceEffect; +import mage.abilities.effects.common.continuous.BoostAllEffect; +import mage.abilities.keyword.TransformAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.filter.FilterPermanent; +import mage.filter.StaticFilters; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.ObjectSourcePlayer; +import mage.filter.predicate.ObjectSourcePlayerPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.util.CardUtil; + +import java.util.Optional; +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class ZenosYaeGalvus extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); + private static final FilterPermanent filter2 = new FilterPermanent(); + + static { + filter.add(ZenosYaeGalvusPredicate.FALSE); + filter2.add(ZenosYaeGalvusPredicate.TRUE); + } + + public ZenosYaeGalvus(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}{B}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.NOBLE); + this.subtype.add(SubType.WARRIOR); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + this.secondSideCardClazz = mage.cards.s.ShinryuTranscendentRival.class; + + // My First Friend -- When Zenos yae Galvus enters, choose a creature an opponent controls. Until end of turn, creatures other than Zenos yae Galvus and the chosen creature get -2/-2. + Ability ability = new EntersBattlefieldTriggeredAbility( + new ChooseCreatureEffect(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE, false) + ); + ability.addEffect(new BoostAllEffect( + -2, -2, Duration.EndOfTurn, filter, true + ).setText("until end of turn, creatures other than {this} and the chosen creature get -2/-2")); + this.addAbility(ability.withFlavorWord("My First Friend")); + + // When the chosen creature leaves the battlefield, transform Zenos yae Galvus. + this.addAbility(new TransformAbility()); + this.addAbility(new LeavesBattlefieldAllTriggeredAbility( + new TransformSourceEffect(), filter2 + ).setTriggerPhrase("When the chosen creature leaves the battlefield, ")); + } + + private ZenosYaeGalvus(final ZenosYaeGalvus card) { + super(card); + } + + @Override + public ZenosYaeGalvus copy() { + return new ZenosYaeGalvus(this); + } +} + +enum ZenosYaeGalvusPredicate implements ObjectSourcePlayerPredicate { + TRUE(true), + FALSE(false); + private final boolean flag; + + ZenosYaeGalvusPredicate(boolean flag) { + this.flag = flag; + } + + @Override + public boolean apply(ObjectSourcePlayer input, Game game) { + return flag == Optional + .ofNullable(CardUtil.getObjectZoneString( + "chosenCreature", input.getSource().getSourceId(), game, + input.getSource().getSourceObjectZoneChangeCounter(), false + )) + .map(game.getState()::getValue) + .filter(MageObjectReference.class::isInstance) + .map(MageObjectReference.class::cast) + .map(mor -> mor.refersTo(input.getObject(), game)) + .orElse(false); + } +} diff --git a/Mage.Sets/src/mage/sets/FinalFantasy.java b/Mage.Sets/src/mage/sets/FinalFantasy.java index 4e01374f3d6..9c0afe48b9c 100644 --- a/Mage.Sets/src/mage/sets/FinalFantasy.java +++ b/Mage.Sets/src/mage/sets/FinalFantasy.java @@ -28,6 +28,7 @@ public final class FinalFantasy extends ExpansionSet { cards.add(new SetCardInfo("Jumbo Cactuar", 191, Rarity.RARE, mage.cards.j.JumboCactuar.class)); cards.add(new SetCardInfo("Sazh's Chocobo", 200, Rarity.UNCOMMON, mage.cards.s.SazhsChocobo.class)); cards.add(new SetCardInfo("Sephiroth, Planet's Heir", 553, Rarity.MYTHIC, mage.cards.s.SephirothPlanetsHeir.class)); + cards.add(new SetCardInfo("Shinryu, Transcendent Rival", 127, Rarity.RARE, mage.cards.s.ShinryuTranscendentRival.class)); cards.add(new SetCardInfo("Sidequest: Catch a Fish", 31, Rarity.UNCOMMON, mage.cards.s.SidequestCatchAFish.class)); cards.add(new SetCardInfo("Sin, Spira's Punishment", 242, Rarity.RARE, mage.cards.s.SinSpirasPunishment.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Sin, Spira's Punishment", 348, Rarity.RARE, mage.cards.s.SinSpirasPunishment.class, NON_FULL_USE_VARIOUS)); @@ -37,5 +38,6 @@ public final class FinalFantasy extends ExpansionSet { cards.add(new SetCardInfo("Summon: Shiva", 78, Rarity.UNCOMMON, mage.cards.s.SummonShiva.class)); cards.add(new SetCardInfo("Tonberry", 122, Rarity.UNCOMMON, mage.cards.t.Tonberry.class)); cards.add(new SetCardInfo("Zell Dincht", 170, Rarity.RARE, mage.cards.z.ZellDincht.class)); + cards.add(new SetCardInfo("Zenos yae Galvus", 127, Rarity.RARE, mage.cards.z.ZenosYaeGalvus.class)); } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/ChooseCreatureEffect.java b/Mage/src/main/java/mage/abilities/effects/common/ChooseCreatureEffect.java index 654f839dc4c..a88e729a4da 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/ChooseCreatureEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/ChooseCreatureEffect.java @@ -13,27 +13,30 @@ import mage.target.TargetPermanent; import mage.util.CardUtil; /** - * To be used with AsEntersBattlefieldAbility (otherwise Zone Change Counter will be wrong) + * To be used with AsEntersBattlefieldAbility with useOffset=false (otherwise Zone Change Counter will be wrong) * * @author weirddan455 */ public class ChooseCreatureEffect extends OneShotEffect { private final FilterPermanent filter; + private final boolean useOffset; public ChooseCreatureEffect() { - this(StaticFilters.FILTER_ANOTHER_CREATURE_YOU_CONTROL); + this(StaticFilters.FILTER_ANOTHER_CREATURE_YOU_CONTROL, true); } - public ChooseCreatureEffect(FilterPermanent filter) { + public ChooseCreatureEffect(FilterPermanent filter, boolean useOffset) { super(Outcome.Benefit); this.filter = filter; this.staticText = "choose " + filter.getMessage(); + this.useOffset = useOffset; } private ChooseCreatureEffect(final ChooseCreatureEffect effect) { super(effect); this.filter = effect.filter; + this.useOffset = effect.useOffset; } @Override @@ -44,11 +47,8 @@ public class ChooseCreatureEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - if (controller == null) { - return false; - } Permanent sourcePermanent = game.getPermanentEntering(source.getSourceId()); - if (sourcePermanent == null) { + if (controller == null || sourcePermanent == null) { return false; } TargetPermanent target = new TargetPermanent(1, 1, filter, true); @@ -58,7 +58,10 @@ public class ChooseCreatureEffect extends OneShotEffect { return false; } game.getState().setValue( - CardUtil.getObjectZoneString("chosenCreature", sourcePermanent.getId(), game, sourcePermanent.getZoneChangeCounter(game) + 1, false), + CardUtil.getObjectZoneString( + "chosenCreature", sourcePermanent.getId(), game, + sourcePermanent.getZoneChangeCounter(game) + (useOffset ? 1 : 0), false + ), new MageObjectReference(chosenCreature, game) ); sourcePermanent.addInfo("chosen creature", CardUtil.addToolTipMarkTags("Chosen Creature " + chosenCreature.getIdName()), game); diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt index 492da7a86cc..72346722bb5 100644 --- a/Utils/mtg-cards-data.txt +++ b/Utils/mtg-cards-data.txt @@ -57190,6 +57190,8 @@ Summon: Shiva|Final Fantasy|78|U|{3}{U}{U}|Enchantment Creature - Saga Elemental Cecil, Dark Knight|Final Fantasy|91|R|{B}|Legendary Creature - Human Knight|2|3|Deathtouch$Darkness -- Whenever Cecil deals damage, you lose that much life. Then if your life total is less than or equal to half your starting life total, untap Cecil and transform it.| Cecil, Redeemed Paladin|Final Fantasy|91|R||Legendary Creature - Human Knight|4|4|Lifelink$Protect -- Whenever Cecil attacks, other attacking creatures gain indestructible until end of turn.| Tonberry|Final Fantasy|122|U|{B}|Creature - Salamander Horror|2|1|This creature enters tapped with a stun counter on it.$Chef's Knife -- During your turn, this creature has first strike and deathtouch.| +Zenos yae Galvus|Final Fantasy|127|R|{3}{B}{B}|Legendary Creature - Human Noble Warrior|4|4|My First Friend -- When Zenos yae Galvus enters, choose a creature an opponent controls. Until end of turn, creatures other than Zenos yae Galvus and the chosen creature get -2/-2.$When the chosen creature leaves the battlefield, transform Zenos yae Galvus.| +Shinryu, Transcendent Rival|Final Fantasy|127|R||Legendary Creature - Human Noble Warrior FP|4|4|Flying$As this creature transforms into Shinryu, choose an opponent.$Burning Chains -- When the chosen player loses the game, you win the game.| Zell Dincht|Final Fantasy|170|R|{2}{R}|Legendary Creature - Human Monk|0|3|You may play an additional land on each of your turns.$Zell Dincht gets +1/+0 for each land you control.$At the beginning of your end step, return a land you control to its owner's hand.| Jumbo Cactuar|Final Fantasy|191|R|{5}{G}{G}|Creature - Plant|1|7|10,000 Needles -- Whenever this creature attacks, it gets +9999/+0 until end of turn.| Sazh's Chocobo|Final Fantasy|200|U|{G}|Creature - Bird|0|1|Landfall -- Whenever a land you control enters, put a +1/+1 counter on this creature.|