From f42fc0f388fbaab393f964aaa682dfa5c0aadbb1 Mon Sep 17 00:00:00 2001 From: grimreap124 <19590931+grimreap124@users.noreply.github.com> Date: Sat, 7 Sep 2024 14:57:36 +1000 Subject: [PATCH] [ACR] Implement The Capitoline Triad (#12510) * Implement-ACR-The-Capitoline-Triad --------- Co-authored-by: Grath <1895280+Grath@users.noreply.github.com> --- .../src/mage/cards/t/TheCapitolineTriad.java | 186 ++++++++++++++++++ Mage.Sets/src/mage/sets/AssassinsCreed.java | 1 + .../common/ManaValueInGraveyard.java | 75 +++++++ .../emblems/TheCapitolineTriadEmblem.java | 32 +++ Mage/src/main/resources/tokens-database.txt | 1 + 5 files changed, 295 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/t/TheCapitolineTriad.java create mode 100644 Mage/src/main/java/mage/abilities/dynamicvalue/common/ManaValueInGraveyard.java create mode 100644 Mage/src/main/java/mage/game/command/emblems/TheCapitolineTriadEmblem.java diff --git a/Mage.Sets/src/mage/cards/t/TheCapitolineTriad.java b/Mage.Sets/src/mage/cards/t/TheCapitolineTriad.java new file mode 100644 index 00000000000..1b00eec46b6 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TheCapitolineTriad.java @@ -0,0 +1,186 @@ +package mage.cards.t; + +import java.awt.*; +import java.util.Collection; +import java.util.Objects; +import java.util.UUID; + +import mage.MageInt; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.Cost; +import mage.abilities.costs.CostImpl; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount; +import mage.abilities.dynamicvalue.common.ManaValueInGraveyard; +import mage.abilities.effects.common.GetEmblemEffect; +import mage.abilities.effects.common.cost.SpellCostReductionForEachSourceEffect; +import mage.abilities.hint.HintUtils; +import mage.abilities.hint.ValueHint; +import mage.constants.*; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.filter.FilterCard; +import mage.filter.predicate.mageobject.HistoricPredicate; +import mage.game.Game; +import mage.game.command.emblems.TheCapitolineTriadEmblem; +import mage.players.Player; +import mage.target.common.TargetCardInYourGraveyard; +import mage.util.CardUtil; + +/** + * @author grimreap124, Grath + */ +public final class TheCapitolineTriad extends CardImpl { + + private static final FilterCard filter = new FilterCard("historic card"); + private static final DynamicValue costXValue = new CardsInControllerGraveyardCount(filter); + private static final DynamicValue manaValueGraveyard = new ManaValueInGraveyard(filter); + + static { + filter.add(HistoricPredicate.instance); + } + + public TheCapitolineTriad(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{10}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.GOD); + this.subtype.add(SubType.ARTIFICER); + this.power = new MageInt(7); + this.toughness = new MageInt(7); + + // Those Who Came Before - This spell costs 1 less to cast for each historic card in your graveyard. + DynamicValue xValue = new CardsInControllerGraveyardCount(filter); + Ability ability = new SimpleStaticAbility(Zone.ALL, new SpellCostReductionForEachSourceEffect(1, xValue)); + ability.setRuleAtTheTop(true); + ability.addHint(new ValueHint("Historic cards in your graveyard", costXValue)); + ability.withFlavorWord("Those Who Came Before"); + this.addAbility(ability); + + + // Exile any number of historic cards from your graveyard with total mana value 30 or greater: You get an emblem with "Creatures you control have base power and toughness 9/9." + ability = new SimpleActivatedAbility(new GetEmblemEffect(new TheCapitolineTriadEmblem()), new TheCapitolineTriadCost()); + ability.addHint(new ValueHint("Mana value of historic cards in graveyard", manaValueGraveyard)); + this.addAbility(ability); + } + + private TheCapitolineTriad(final TheCapitolineTriad card) { + super(card); + } + + @Override + public TheCapitolineTriad copy() { + return new TheCapitolineTriad(this); + } +} + +class TheCapitolineTriadCost extends CostImpl { + + public TheCapitolineTriadCost() { + this.addTarget(new TheCapitolineTriadTarget()); + this.text = "exile any number of historic cards from your graveyard with total mana value 30 or greater"; + } + + private TheCapitolineTriadCost(final TheCapitolineTriadCost cost) { + super(cost); + } + + @Override + public boolean pay(Ability ability, Game game, Ability source, UUID controllerId, boolean noMana, Cost costToPay) { + Player player = game.getPlayer(controllerId); + int sumManaValue = 0; + if (this.getTargets().choose(Outcome.Exile, controllerId, source.getSourceId(), source, game)) { + for (UUID targetId : this.getTargets().get(0).getTargets()) { + Card card = game.getCard(targetId); + if (card != null && player.moveCardsToExile(card, source, game, true, CardUtil.getExileZoneId(game, source), CardUtil.getSourceName(game, source))) { + sumManaValue += card.getManaValue(); + } + } + } + game.informPlayers("Exile historic cards with total mana value of " + sumManaValue); + paid = sumManaValue >= 30; + return paid; + } + + @Override + public boolean canPay(Ability ability, Ability source, UUID controllerId, Game game) { + Player player = game.getPlayer(controllerId); + int sumManaValue = 0; + for (UUID cardId : player.getGraveyard()) { + Card card = game.getCard(cardId); + if (card != null) { + sumManaValue += card.getManaValue(); + } + } + return sumManaValue >= 30; + } + + @Override + public TheCapitolineTriadCost copy() { + return new TheCapitolineTriadCost(this); + } +} + +class TheCapitolineTriadTarget extends TargetCardInYourGraveyard { + + private static final FilterCard filter = new FilterCard("historic cards"); + + static { + filter.add(HistoricPredicate.instance); + } + + TheCapitolineTriadTarget() { + super(1, Integer.MAX_VALUE, filter, true); + } + + private TheCapitolineTriadTarget(final TheCapitolineTriadTarget target) { + super(target); + } + + @Override + public TheCapitolineTriadTarget copy() { + return new TheCapitolineTriadTarget(this); + } + + @Override + public boolean isChosen(Game game) { + return super.isChosen(game) && metCondition(this.getTargets(), game); + } + + @Override + public String getMessage(Game game) { + String text = "Select " + targetName; + int manaValueOfSelection = manaValueOfSelection(this.getTargets(), game); + text += " (selected " + this.getTargets().size() + " cards; mana value: "; + text += HintUtils.prepareText( + manaValueOfSelection + " of 30", + manaValueOfSelection >= 30 ? Color.GREEN : Color.RED + ); + text +=")"; + return text; + } + + @Override + public boolean canChoose(UUID sourceControllerId, Ability source, Game game) { + if (!super.canChoose(sourceControllerId, source, game)) { + return false; + } + // Check that exiling all the possible cards would have >= 4 different card types + return metCondition(this.possibleTargets(sourceControllerId, source, game), game); + } + + private static int manaValueOfSelection(Collection cardsIds, Game game) { + return cardsIds + .stream() + .map(game::getCard) + .filter(Objects::nonNull).mapToInt(MageObject::getManaValue).sum(); + } + + private static boolean metCondition(Collection cardsIds, Game game) { + return manaValueOfSelection(cardsIds, game) >= 30; + } +} diff --git a/Mage.Sets/src/mage/sets/AssassinsCreed.java b/Mage.Sets/src/mage/sets/AssassinsCreed.java index d79ec01bfc3..7a0e8bd2cea 100644 --- a/Mage.Sets/src/mage/sets/AssassinsCreed.java +++ b/Mage.Sets/src/mage/sets/AssassinsCreed.java @@ -125,6 +125,7 @@ public final class AssassinsCreed extends ExpansionSet { cards.add(new SetCardInfo("Temporal Trespass", 86, Rarity.MYTHIC, mage.cards.t.TemporalTrespass.class)); cards.add(new SetCardInfo("Terminate", 98, Rarity.UNCOMMON, mage.cards.t.Terminate.class)); cards.add(new SetCardInfo("The Animus", 69, Rarity.RARE, mage.cards.t.TheAnimus.class)); + cards.add(new SetCardInfo("The Capitoline Triad", 1, Rarity.MYTHIC, mage.cards.t.TheCapitolineTriad.class)); cards.add(new SetCardInfo("The Revelations of Ezio", 31, Rarity.UNCOMMON, mage.cards.t.TheRevelationsOfEzio.class)); cards.add(new SetCardInfo("The Spear of Leonidas", 38, Rarity.RARE, mage.cards.t.TheSpearOfLeonidas.class)); cards.add(new SetCardInfo("Towering Viewpoint", 77, Rarity.UNCOMMON, mage.cards.t.ToweringViewpoint.class)); diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/ManaValueInGraveyard.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/ManaValueInGraveyard.java new file mode 100644 index 00000000000..752a637cde0 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/ManaValueInGraveyard.java @@ -0,0 +1,75 @@ +package mage.abilities.dynamicvalue.common; + +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.effects.Effect; +import mage.filter.FilterCard; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.players.Player; + +import java.util.Objects; +import java.util.UUID; + +/** + * @author grimreap124 + */ +public class ManaValueInGraveyard implements DynamicValue { + + private final FilterCard filter; + private final Integer multiplier; + + public ManaValueInGraveyard() { + this(StaticFilters.FILTER_CARD, 1); + } + + public ManaValueInGraveyard(FilterCard filter) { + this(filter, 1); + } + + public ManaValueInGraveyard(FilterCard filter, Integer multiplier) { + this.filter = filter; + this.multiplier = multiplier; + } + + protected ManaValueInGraveyard(final ManaValueInGraveyard dynamicValue) { + this.filter = dynamicValue.filter; + this.multiplier = dynamicValue.multiplier; + } + + @Override + public int calculate(Game game, Ability sourceAbility, Effect effect) { + UUID playerId = sourceAbility.getControllerId(); + Player player = game.getPlayer(playerId); + if (player == null) { + return 0; + } + int value = player.getGraveyard().stream().map(game::getCard).filter(Objects::nonNull) + .filter(card -> filter.match(card, playerId, game)).mapToInt(MageObject::getManaValue).sum(); + if (multiplier != null) { + value *= multiplier; + } + return value; + } + + @Override + public ManaValueInGraveyard copy() { + return new ManaValueInGraveyard(this); + } + + @Override + public String toString() { + return multiplier == null ? "X" : multiplier.toString(); + } + + @Override + public String getMessage() { + return (multiplier == null ? "the mana value of " : "") + filter.getMessage() + " in your graveyard"; + } + + @Override + public int getSign() { + return multiplier == null ? 1 : multiplier; + } +} diff --git a/Mage/src/main/java/mage/game/command/emblems/TheCapitolineTriadEmblem.java b/Mage/src/main/java/mage/game/command/emblems/TheCapitolineTriadEmblem.java new file mode 100644 index 00000000000..956509658c3 --- /dev/null +++ b/Mage/src/main/java/mage/game/command/emblems/TheCapitolineTriadEmblem.java @@ -0,0 +1,32 @@ +package mage.game.command.emblems; + +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.continuous.*; +import mage.constants.Duration; +import mage.constants.Zone; +import mage.filter.StaticFilters; +import mage.game.command.Emblem; + +/* + * @author grimreap124 + */ +public final class TheCapitolineTriadEmblem extends Emblem { + + public TheCapitolineTriadEmblem() { + super("Emblem Capitoline Triad"); + // You get an emblem with "Creatures you control have base power and toughness 9/9." + Ability ability = new SimpleStaticAbility(Zone.COMMAND, + new SetBasePowerToughnessAllEffect(9, 9, Duration.EndOfGame, StaticFilters.FILTER_PERMANENT_CREATURES_CONTROLLED).setText("Creatures you control have base power and toughness 9/9.")); + getAbilities().add(ability); + } + + private TheCapitolineTriadEmblem(final TheCapitolineTriadEmblem card) { + super(card); + } + + @Override + public TheCapitolineTriadEmblem copy() { + return new TheCapitolineTriadEmblem(this); + } +} diff --git a/Mage/src/main/resources/tokens-database.txt b/Mage/src/main/resources/tokens-database.txt index 6fde7efd7db..3583bd93d00 100644 --- a/Mage/src/main/resources/tokens-database.txt +++ b/Mage/src/main/resources/tokens-database.txt @@ -134,6 +134,7 @@ |Generate|EMBLEM:MH3|Emblem Tamiyo|||TamiyoSeasonedScholarEmblem| |Generate|EMBLEM:M3C|Emblem Garruk|||GarrukApexPredatorEmblem| |Generate|EMBLEM:M3C|Emblem Vivien|||VivienReidEmblem| +|Generate|EMBLEM:ACR|Emblem Capitoline Triad|||TheCapitolineTriadEmblem| |Generate|EMBLEM:BLB|Emblem Ral|||RalCracklingWitEmblem| # ALL PLANES