Added WinterCynicalOpportunist.java card to the DuskmournHouseOfHorrorCommander set and card.

This commit is contained in:
Lashed 2025-05-04 18:58:01 +02:00
parent 5b687c344e
commit 56ccfd2630
2 changed files with 221 additions and 6 deletions

View file

@ -0,0 +1,220 @@
package mage.cards.w;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.AttacksTriggeredAbility;
import mage.abilities.condition.common.DeliriumCondition;
import mage.abilities.dynamicvalue.common.CardTypesInGraveyardCount;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.MillCardsControllerEffect;
import mage.abilities.hint.HintUtils;
import mage.abilities.keyword.DeathtouchAbility;
import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility;
import mage.cards.*;
import mage.constants.*;
import mage.counters.CounterType;
import mage.filter.FilterCard;
import mage.filter.StaticFilters;
import mage.filter.common.FilterPermanentCard;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetCard;
import mage.target.common.TargetCardInYourGraveyard;
import mage.util.CardUtil;
import java.awt.*;
import java.util.Collection;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
/**
*
* @author Lashed
*/
public final class WinterCynicalOpportunist extends CardImpl {
public WinterCynicalOpportunist(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}{G}");
this.supertype.add(SuperType.LEGENDARY);
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.WARLOCK);
this.power = new MageInt(2);
this.toughness = new MageInt(5);
// Deathtouch
this.addAbility(DeathtouchAbility.getInstance());
// Whenever Winter attacks, mill three cards.
this.addAbility(new AttacksTriggeredAbility(new MillCardsControllerEffect(3), false));
// Delirium -- At the beginning of your end step, you may exile any number of cards from your graveyard with four or more card types among them. If you do, put a permanent card from among them onto the battlefield with a finality counter on it.
this.addAbility(new BeginningOfEndStepTriggeredAbility(
TargetController.YOU,
new WinterCynicalOpportunistDeliriumEffect(),
true)
.setAbilityWord(AbilityWord.DELIRIUM)
.withInterveningIf(DeliriumCondition.instance)
.addHint(CardTypesInGraveyardCount.YOU.getHint()));
}
private WinterCynicalOpportunist(final WinterCynicalOpportunist card) {
super(card);
}
@Override
public WinterCynicalOpportunist copy() {
return new WinterCynicalOpportunist(this);
}
}
class WinterCynicalOpportunistDeliriumEffect extends OneShotEffect {
public WinterCynicalOpportunistDeliriumEffect() {
super(Outcome.PutCardInPlay);
this.staticText = "exile any number of cards from your graveyard. " +
"If you do, put a permanent card from among them onto the battlefield with a finality counter on it";
}
private WinterCynicalOpportunistDeliriumEffect(final WinterCynicalOpportunistDeliriumEffect effect) {
super(effect);
}
@Override
public WinterCynicalOpportunistDeliriumEffect copy() {
return new WinterCynicalOpportunistDeliriumEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
MageObject sourceObject = source.getSourceObject(game);
if (controller == null || sourceObject == null) {
return false;
}
// Let the player select cards to exile
DeliriumTarget target = new DeliriumTarget();
if (!target.canChoose(controller.getId(), source, game) ||
!controller.choose(Outcome.Exile, target, source, game)) {
return false;
}
// Exile the selected cards
Set<Card> cardsToExile = target.getTargets().stream()
.map(game::getCard)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
if (cardsToExile.isEmpty()) {
return false;
}
controller.moveCards(cardsToExile, Zone.EXILED, source, game);
// Filter permanent cards from the exiled cards
FilterCard filter = new FilterPermanentCard("permanent card from among the exiled cards to put onto the battlefield");
filter.add(new WinterCynicalOpportunistExiledPredicate(cardsToExile));
TargetCard targetPermanent = new TargetCard(1, 1, Zone.EXILED, filter);
Cards permanentCards = new CardsImpl();
cardsToExile.stream()
.filter(card -> card.isPermanent(game))
.forEach(permanentCards::add);
if (controller.choose(Outcome.PutCardInPlay, permanentCards, targetPermanent, source, game)) {
Card cardToPut = game.getCard(targetPermanent.getFirstTarget());
if (cardToPut != null) {
controller.moveCards(cardToPut, Zone.BATTLEFIELD, source, game);
// Add a finality counter
Card permanentCard = game.getPermanent(cardToPut.getId());
if (permanentCard != null) {
permanentCard.addCounters(CounterType.FINALITY.createInstance(), source.getControllerId(), source, game);
}
return true;
}
}
return false;
}
}
class DeliriumTarget extends TargetCardInYourGraveyard {
DeliriumTarget() {
super(0, Integer.MAX_VALUE, StaticFilters.FILTER_CARD, true);
this.targetName = "any number of cards from your graveyard";
}
private DeliriumTarget(final DeliriumTarget target) {
super(target);
}
@Override
public DeliriumTarget copy() {
return new DeliriumTarget(this);
}
@Override
public String getMessage(Game game) {
String text = "Select " + CardUtil.addArticle(targetName);
Set<CardType> types = getCardTypes(this.getTargets(), game);
text += " (selected " + this.getTargets().size() + " cards; card types: ";
text += HintUtils.prepareText(
types.size() + " of 4",
types.size() >= 4 ? Color.GREEN : Color.RED
);
text += " [" + types.stream().map(CardType::toString).collect(Collectors.joining(", ")) + "])";
return text;
}
@Override
public boolean isChosen(Game game) {
return super.isChosen(game) && getCardTypesCount(this.getTargets(), game) >= 4;
}
@Override
public boolean canChoose(UUID sourceControllerId, Ability source, Game game) {
if (!super.canChoose(sourceControllerId, source, game)) {
return false;
}
// Check that selecting all the possible cards would have >= 4 different card types
return getCardTypesCount(this.possibleTargets(sourceControllerId, source, game), game) >= 4;
}
private static Set<CardType> getCardTypes(Collection<UUID> cardIds, Game game) {
return cardIds
.stream()
.map(game::getCard)
.filter(Objects::nonNull)
.flatMap(c -> c.getCardType(game).stream())
.collect(Collectors.toSet());
}
private static int getCardTypesCount(Collection<UUID> cardIds, Game game) {
return getCardTypes(cardIds, game).size();
}
}
class WinterCynicalOpportunistExiledPredicate implements mage.filter.predicate.Predicate<Card> {
private final Set<Card> exiledCards;
public WinterCynicalOpportunistExiledPredicate(Set<Card> exiledCards) {
this.exiledCards = exiledCards;
}
@Override
public boolean apply(Card input, Game game) {
return exiledCards.contains(input);
}
}

View file

@ -23,7 +23,6 @@ public final class DuskmournHouseOfHorrorCommander extends ExpansionSet {
cards.add(new SetCardInfo("Aesi, Tyrant of Gyre Strait", 210, Rarity.MYTHIC, mage.cards.a.AesiTyrantOfGyreStrait.class));
cards.add(new SetCardInfo("Aether Gale", 109, Rarity.RARE, mage.cards.a.AetherGale.class));
cards.add(new SetCardInfo("Aminatou's Augury", 71, Rarity.RARE, mage.cards.a.AminatousAugury.class));
cards.add(new SetCardInfo("Ancient Cellarspawn", 16, Rarity.RARE, mage.cards.a.AncientCellarspawn.class));
cards.add(new SetCardInfo("Arachnogenesis", 169, Rarity.RARE, mage.cards.a.Arachnogenesis.class));
cards.add(new SetCardInfo("Arcane Denial", 110, Rarity.COMMON, mage.cards.a.ArcaneDenial.class));
cards.add(new SetCardInfo("Arcane Sanctum", 259, Rarity.UNCOMMON, mage.cards.a.ArcaneSanctum.class));
@ -39,7 +38,6 @@ public final class DuskmournHouseOfHorrorCommander extends ExpansionSet {
cards.add(new SetCardInfo("Auramancer", 97, Rarity.COMMON, mage.cards.a.Auramancer.class));
cards.add(new SetCardInfo("Azorius Chancery", 261, Rarity.UNCOMMON, mage.cards.a.AzoriusChancery.class));
cards.add(new SetCardInfo("Azorius Signet", 240, Rarity.UNCOMMON, mage.cards.a.AzoriusSignet.class));
cards.add(new SetCardInfo("Barbflare Gremlin", 26, Rarity.RARE, mage.cards.b.BarbflareGremlin.class));
cards.add(new SetCardInfo("Barren Moor", 262, Rarity.UNCOMMON, mage.cards.b.BarrenMoor.class));
cards.add(new SetCardInfo("Basilisk Collar", 241, Rarity.RARE, mage.cards.b.BasiliskCollar.class));
cards.add(new SetCardInfo("Bastion of Remembrance", 131, Rarity.UNCOMMON, mage.cards.b.BastionOfRemembrance.class));
@ -90,7 +88,6 @@ public final class DuskmournHouseOfHorrorCommander extends ExpansionSet {
cards.add(new SetCardInfo("Deluge of Doom", 18, Rarity.RARE, mage.cards.d.DelugeOfDoom.class));
cards.add(new SetCardInfo("Demolisher Spawn", 31, Rarity.RARE, mage.cards.d.DemolisherSpawn.class));
cards.add(new SetCardInfo("Demon of Fate's Design", 137, Rarity.RARE, mage.cards.d.DemonOfFatesDesign.class));
cards.add(new SetCardInfo("Demonic Covenant", 19, Rarity.RARE, mage.cards.d.DemonicCovenant.class));
cards.add(new SetCardInfo("Diabolic Vision", 87, Rarity.UNCOMMON, mage.cards.d.DiabolicVision.class));
cards.add(new SetCardInfo("Dig Through Time", 115, Rarity.RARE, mage.cards.d.DigThroughTime.class));
cards.add(new SetCardInfo("Dimir Aqueduct", 270, Rarity.UNCOMMON, mage.cards.d.DimirAqueduct.class));
@ -148,7 +145,6 @@ public final class DuskmournHouseOfHorrorCommander extends ExpansionSet {
cards.add(new SetCardInfo("Infernal Grasp", 143, Rarity.UNCOMMON, mage.cards.i.InfernalGrasp.class));
cards.add(new SetCardInfo("Inkshield", 221, Rarity.RARE, mage.cards.i.Inkshield.class));
cards.add(new SetCardInfo("Inscription of Abundance", 186, Rarity.RARE, mage.cards.i.InscriptionOfAbundance.class));
cards.add(new SetCardInfo("Into the Pit", 20, Rarity.RARE, mage.cards.i.IntoThePit.class));
cards.add(new SetCardInfo("Ishkanah, Grafwidow", 187, Rarity.MYTHIC, mage.cards.i.IshkanahGrafwidow.class));
cards.add(new SetCardInfo("Jungle Hollow", 285, Rarity.COMMON, mage.cards.j.JungleHollow.class));
cards.add(new SetCardInfo("Kaervek the Merciless", 222, Rarity.RARE, mage.cards.k.KaervekTheMerciless.class));
@ -222,7 +218,6 @@ public final class DuskmournHouseOfHorrorCommander extends ExpansionSet {
cards.add(new SetCardInfo("Rendmaw, Creaking Nest", 5, Rarity.MYTHIC, mage.cards.r.RendmawCreakingNest.class));
cards.add(new SetCardInfo("Retreat to Coralhelm", 126, Rarity.UNCOMMON, mage.cards.r.RetreatToCoralhelm.class));
cards.add(new SetCardInfo("Return to Dust", 102, Rarity.UNCOMMON, mage.cards.r.ReturnToDust.class));
cards.add(new SetCardInfo("Sadistic Shell Game", 24, Rarity.RARE, mage.cards.s.SadisticShellGame.class));
cards.add(new SetCardInfo("Sakura-Tribe Elder", 194, Rarity.COMMON, mage.cards.s.SakuraTribeElder.class));
cards.add(new SetCardInfo("Sandwurm Convergence", 195, Rarity.RARE, mage.cards.s.SandwurmConvergence.class));
cards.add(new SetCardInfo("Scavenging Ooze", 196, Rarity.RARE, mage.cards.s.ScavengingOoze.class));
@ -241,7 +236,6 @@ public final class DuskmournHouseOfHorrorCommander extends ExpansionSet {
cards.add(new SetCardInfo("Skaab Ruinator", 128, Rarity.MYTHIC, mage.cards.s.SkaabRuinator.class));
cards.add(new SetCardInfo("Skola Grovedancer", 199, Rarity.COMMON, mage.cards.s.SkolaGrovedancer.class));
cards.add(new SetCardInfo("Smoldering Marsh", 299, Rarity.RARE, mage.cards.s.SmolderingMarsh.class));
cards.add(new SetCardInfo("Soaring Lightbringer", 11, Rarity.RARE, mage.cards.s.SoaringLightbringer.class));
cards.add(new SetCardInfo("Sol Ring", 94, Rarity.UNCOMMON, mage.cards.s.SolRing.class));
cards.add(new SetCardInfo("Solemn Simulacrum", 253, Rarity.RARE, mage.cards.s.SolemnSimulacrum.class));
cards.add(new SetCardInfo("Sphere of Safety", 104, Rarity.UNCOMMON, mage.cards.s.SphereOfSafety.class));
@ -310,6 +304,7 @@ public final class DuskmournHouseOfHorrorCommander extends ExpansionSet {
cards.add(new SetCardInfo("Whispersilk Cloak", 257, Rarity.UNCOMMON, mage.cards.w.WhispersilkCloak.class));
cards.add(new SetCardInfo("Whisperwood Elemental", 204, Rarity.MYTHIC, mage.cards.w.WhisperwoodElemental.class));
cards.add(new SetCardInfo("Wilderness Reclamation", 205, Rarity.UNCOMMON, mage.cards.w.WildernessReclamation.class));
cards.add(new SetCardInfo("Winter, Cynical Opportunist", 7, Rarity.MYTHIC, mage.cards.w.WinterCynicalOpportunist.class));
cards.add(new SetCardInfo("Witch's Clinic", 325, Rarity.RARE, mage.cards.w.WitchsClinic.class));
cards.add(new SetCardInfo("Woodland Cemetery", 326, Rarity.RARE, mage.cards.w.WoodlandCemetery.class));
cards.add(new SetCardInfo("Worldspine Wurm", 206, Rarity.MYTHIC, mage.cards.w.WorldspineWurm.class));