From 89f2efd7a97a318c68f7bb237aa6ee9e6f701291 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Fri, 19 Dec 2025 09:09:08 -0500 Subject: [PATCH] [SLD] Implement Jin Sakai, Ghost of Tsushima --- .../mage/cards/j/JinSakaiGhostOfTsushima.java | 116 ++++++++++++++++++ Mage.Sets/src/mage/sets/SecretLairDrop.java | 1 + 2 files changed, 117 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/j/JinSakaiGhostOfTsushima.java diff --git a/Mage.Sets/src/mage/cards/j/JinSakaiGhostOfTsushima.java b/Mage.Sets/src/mage/cards/j/JinSakaiGhostOfTsushima.java new file mode 100644 index 00000000000..4839a8ce934 --- /dev/null +++ b/Mage.Sets/src/mage/cards/j/JinSakaiGhostOfTsushima.java @@ -0,0 +1,116 @@ +package mage.cards.j; + +import mage.MageInt; +import mage.MageItem; +import mage.abilities.Mode; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.combat.CantBeBlockedTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.DoubleStrikeAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.target.targetpointer.FixedTarget; + +import java.util.Objects; +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class JinSakaiGhostOfTsushima extends CardImpl { + + public JinSakaiGhostOfTsushima(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}{U}{B}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.SAMURAI); + this.power = new MageInt(2); + this.toughness = new MageInt(4); + + // Whenever Jin Sakai deals combat damage to a player, draw a card. + this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new DrawCardSourceControllerEffect(1))); + + // Whenever a creature you control attacks a player, if no other creatures are attacking that player, choose one -- + // * Standoff -- It gains double strike until end of turn. + // * Ghost -- It can't be blocked this turn. + this.addAbility(new JinSakaiGhostOfTsushimaTriggeredAbility()); + } + + private JinSakaiGhostOfTsushima(final JinSakaiGhostOfTsushima card) { + super(card); + } + + @Override + public JinSakaiGhostOfTsushima copy() { + return new JinSakaiGhostOfTsushima(this); + } +} + +class JinSakaiGhostOfTsushimaTriggeredAbility extends TriggeredAbilityImpl { + + JinSakaiGhostOfTsushimaTriggeredAbility() { + super(Zone.BATTLEFIELD, new GainAbilityTargetEffect(DoubleStrikeAbility.getInstance()).withTargetDescription("it")); + this.withFirstModeFlavorWord("Standoff"); + this.addMode(new Mode(new CantBeBlockedTargetEffect().withTargetDescription("it")).withFlavorWord("Ghost")); + this.setTriggerPhrase("Whenever a creature you control attacks a player, if no other creatures are attacking that player, "); + } + + private JinSakaiGhostOfTsushimaTriggeredAbility(final JinSakaiGhostOfTsushimaTriggeredAbility ability) { + super(ability); + } + + @Override + public JinSakaiGhostOfTsushimaTriggeredAbility copy() { + return new JinSakaiGhostOfTsushimaTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.ATTACKER_DECLARED; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + Permanent permanent = game.getPermanent(event.getTargetId()); + if (permanent == null + || !permanent.isControlledBy(getControllerId()) + || game.getPlayer(game.getCombat().getDefenderId(permanent.getId())) == null) { + return false; + } + this.getAllEffects().setTargetPointer(new FixedTarget(permanent, game)); + return true; + } + + @Override + public boolean checkInterveningIfClause(Game game) { + return this + .getAllEffects() + .stream() + .map(Effect::getTargetPointer) + .map(targetPointer -> targetPointer.getFirst(game, this)) + .map(game::getPermanent) + .filter(Objects::nonNull) + .findAny() + .map(MageItem::getId) + .map(game.getCombat()::getDefenderId) + .filter(defenderId -> game + .getCombat() + .getAttackers() + .stream() + .map(game.getCombat()::getDefenderId) + .filter(defenderId::equals) + .count() == 1) + .isPresent(); + } +} diff --git a/Mage.Sets/src/mage/sets/SecretLairDrop.java b/Mage.Sets/src/mage/sets/SecretLairDrop.java index 4fc7205f1d3..ef014c05bf2 100644 --- a/Mage.Sets/src/mage/sets/SecretLairDrop.java +++ b/Mage.Sets/src/mage/sets/SecretLairDrop.java @@ -2178,6 +2178,7 @@ public class SecretLairDrop extends ExpansionSet { cards.add(new SetCardInfo("Blightsteel Colossus", 2223, Rarity.MYTHIC, mage.cards.b.BlightsteelColossus.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Tarrian's Soulcleaver", 2224, Rarity.RARE, mage.cards.t.TarriansSoulcleaver.class)); cards.add(new SetCardInfo("Meteor Golem", 2225, Rarity.RARE, mage.cards.m.MeteorGolem.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Jin Sakai, Ghost of Tsushima", 2226, Rarity.MYTHIC, mage.cards.j.JinSakaiGhostOfTsushima.class)); cards.add(new SetCardInfo("Path to Exile", 2227, Rarity.RARE, mage.cards.p.PathToExile.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Borne Upon a Wind", 2228, Rarity.RARE, mage.cards.b.BorneUponAWind.class)); cards.add(new SetCardInfo("Ghostly Flicker", 2229, Rarity.RARE, mage.cards.g.GhostlyFlicker.class));