From 1e414442b3470fb45df98c57dd036e75d130700f Mon Sep 17 00:00:00 2001 From: Sidorovich77 Date: Thu, 15 Aug 2024 04:10:07 +0300 Subject: [PATCH] [CLU] Implement Apothecary White & Emissary Green (#12642) --- .../src/mage/cards/a/ApothecaryWhite.java | 106 ++++++++++++++++++ Mage.Sets/src/mage/cards/e/EmissaryGreen.java | 94 ++++++++++++++++ .../src/mage/sets/RavnicaClueEdition.java | 2 + 3 files changed, 202 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/a/ApothecaryWhite.java create mode 100644 Mage.Sets/src/mage/cards/e/EmissaryGreen.java diff --git a/Mage.Sets/src/mage/cards/a/ApothecaryWhite.java b/Mage.Sets/src/mage/cards/a/ApothecaryWhite.java new file mode 100644 index 00000000000..a6feda32a02 --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/ApothecaryWhite.java @@ -0,0 +1,106 @@ +package mage.cards.a; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.AttacksWithCreaturesTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.common.TapVariableTargetCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.GetXValue; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.keyword.VigilanceAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.permanent.TappedPredicate; +import mage.game.Game; +import mage.game.combat.CombatGroup; +import mage.game.permanent.token.FoodToken; +import mage.game.permanent.token.HumanToken; + +import java.util.Objects; +import java.util.UUID; + +/** + * @author Sidorovich77 + */ +public final class ApothecaryWhite extends CardImpl { + + static final FilterControlledPermanent filter = new FilterControlledPermanent(SubType.FOOD, "untapped Foods you control"); + + static { + filter.add(TappedPredicate.UNTAPPED); + } + + public ApothecaryWhite(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.CLERIC); + this.power = new MageInt(3); + this.toughness = new MageInt(4); + + // Vigilance + this.addAbility(VigilanceAbility.getInstance()); + + // Whenever you attack, you create a Food token for each player being attacked. + this.addAbility(new AttacksWithCreaturesTriggeredAbility( + new CreateTokenEffect(new FoodToken(), ApothecaryWhiteValue.instance) + .setText("you create a Food token for each player being attacked."), 1)); + // {W}, {T}, Tap X untapped Foods you control: Create X 1/1 white Human creature tokens. + Ability ability = new SimpleActivatedAbility(new CreateTokenEffect(new HumanToken(), GetXValue.instance), new ManaCostsImpl<>("{W}")); + ability.addCost(new TapSourceCost()); + ability.addCost(new TapVariableTargetCost(filter)); + this.addAbility(ability); + } + + private ApothecaryWhite(final ApothecaryWhite card) { + super(card); + } + + @Override + public ApothecaryWhite copy() { + return new ApothecaryWhite(this); + } +} + +enum ApothecaryWhiteValue implements DynamicValue { + instance; + + @Override + public int calculate(Game game, Ability sourceAbility, Effect effect) { + return game + .getCombat() + .getGroups() + .stream() + .filter(combatGroup -> combatGroup + .getAttackers() + .stream() + .map(game::getControllerId) + .anyMatch(sourceAbility::isControlledBy)) + .map(CombatGroup::getDefenderId) + .filter(Objects::nonNull) + .distinct() + .map(game::getPlayer) + .filter(Objects::nonNull) + .mapToInt(x -> 1) + .sum(); + } + + @Override + public ApothecaryWhiteValue copy() { + return this; + } + + @Override + public String getMessage() { + return "player being attacked."; + } +} diff --git a/Mage.Sets/src/mage/cards/e/EmissaryGreen.java b/Mage.Sets/src/mage/cards/e/EmissaryGreen.java new file mode 100644 index 00000000000..40190841841 --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/EmissaryGreen.java @@ -0,0 +1,94 @@ +package mage.cards.e; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.dynamicvalue.common.StaticValue; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.counter.AddCountersAllEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.choices.TwoChoiceVote; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.counters.CounterType; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.game.permanent.token.TreasureToken; + +import java.util.UUID; + +/** + * @author Sidorovich77 + */ +public final class EmissaryGreen extends CardImpl { + + public EmissaryGreen(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{G}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.ADVISOR); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + //Whenever Emissary Green attacks, starting with you, each player votes for profit or security. + // You create a number of Treasure tokens equal to twice the number of profit votes. + // Put a number of +1/+1 counters on each creature you control equal to the number of security votes. + this.addAbility(new AttacksTriggeredAbility(new EmissaryGreenEffect())); + } + + private EmissaryGreen(final EmissaryGreen card) { + super(card); + } + + @Override + public EmissaryGreen copy() { + return new EmissaryGreen(this); + } +} + +class EmissaryGreenEffect extends OneShotEffect { + + EmissaryGreenEffect() { + super(Outcome.Benefit); + staticText = "starting with you, each player votes for profit or security. " + + "You create a number of Treasure tokens equal to twice the number of profit votes. " + + "Put a number of +1/+1 counters on each creature you control equal to the number of security votes."; + } + + private EmissaryGreenEffect(final EmissaryGreenEffect effect) { + super(effect); + } + + @Override + public EmissaryGreenEffect copy() { + return new EmissaryGreenEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + TwoChoiceVote vote = new TwoChoiceVote( + "Profit (treasure)", "Security (+1/+1 counters)", Outcome.Detriment + ); + vote.doVotes(source, game); + int profitCounter = vote.getVoteCount(true); + int securityCounter = vote.getVoteCount(false); + if (profitCounter > 0) { + new TreasureToken().putOntoBattlefield(2 * profitCounter, game, source); + } + if (securityCounter > 0) { + AddCountersAllEffect countersAllEffect = new AddCountersAllEffect( + CounterType.P1P1.createInstance(), + StaticValue.get(securityCounter), + StaticFilters.FILTER_CONTROLLED_CREATURE + ); + countersAllEffect.setText("put a number of +1/+1 counters on each creature you control equal to the number of security votes."); + countersAllEffect.apply(game, source); + + } + return profitCounter + securityCounter > 0; + } +} diff --git a/Mage.Sets/src/mage/sets/RavnicaClueEdition.java b/Mage.Sets/src/mage/sets/RavnicaClueEdition.java index 723c7e150f0..67bd9048811 100644 --- a/Mage.Sets/src/mage/sets/RavnicaClueEdition.java +++ b/Mage.Sets/src/mage/sets/RavnicaClueEdition.java @@ -25,6 +25,7 @@ public final class RavnicaClueEdition extends ExpansionSet { cards.add(new SetCardInfo("Afterlife Insurance", 23, Rarity.UNCOMMON, mage.cards.a.AfterlifeInsurance.class)); cards.add(new SetCardInfo("Ajani's Pridemate", 52, Rarity.UNCOMMON, mage.cards.a.AjanisPridemate.class)); cards.add(new SetCardInfo("Angel of Vitality", 53, Rarity.UNCOMMON, mage.cards.a.AngelOfVitality.class)); + cards.add(new SetCardInfo("Apothecary White", 1, Rarity.RARE, mage.cards.a.ApothecaryWhite.class)); cards.add(new SetCardInfo("Azorius Arrester", 54, Rarity.COMMON, mage.cards.a.AzoriusArrester.class)); cards.add(new SetCardInfo("Azorius Chancery", 229, Rarity.COMMON, mage.cards.a.AzoriusChancery.class)); cards.add(new SetCardInfo("Azorius Guildgate", 230, Rarity.COMMON, mage.cards.a.AzoriusGuildgate.class)); @@ -81,6 +82,7 @@ public final class RavnicaClueEdition extends ExpansionSet { cards.add(new SetCardInfo("Duskmantle Seer", 188, Rarity.MYTHIC, mage.cards.d.DuskmantleSeer.class)); cards.add(new SetCardInfo("Duskshell Crawler", 161, Rarity.COMMON, mage.cards.d.DuskshellCrawler.class)); cards.add(new SetCardInfo("Ecstatic Electromancer", 31, Rarity.UNCOMMON, mage.cards.e.EcstaticElectromancer.class)); + cards.add(new SetCardInfo("Emissary Green", 5, Rarity.RARE, mage.cards.e.EmissaryGreen.class)); cards.add(new SetCardInfo("Enforcer Griffin", 60, Rarity.COMMON, mage.cards.e.EnforcerGriffin.class)); cards.add(new SetCardInfo("Enraged Ceratok", 162, Rarity.UNCOMMON, mage.cards.e.EnragedCeratok.class)); cards.add(new SetCardInfo("Erratic Visionary", 85, Rarity.COMMON, mage.cards.e.ErraticVisionary.class));