From 7a8dd704cf07199fa7036f52021f9d6d4459f37e Mon Sep 17 00:00:00 2001 From: PurpleCrowbar <26198472+PurpleCrowbar@users.noreply.github.com> Date: Sat, 6 Aug 2022 20:28:37 +0100 Subject: [PATCH] [NCC] Implement Kros, Defense Contractor (#9362) --- .../src/mage/cards/g/GenerousPatron.java | 58 +++-------- .../mage/cards/h/HapatraVizierOfPoisons.java | 49 +--------- .../mage/cards/k/KrosDefenseContractor.java | 95 +++++++++++++++++++ Mage.Sets/src/mage/cards/n/NestOfScarabs.java | 55 +---------- Mage.Sets/src/mage/cards/o/ObeliskSpider.java | 50 +--------- .../src/mage/sets/NewCapennaCommander.java | 2 + .../PutCounterOnCreatureTriggeredAbility.java | 89 +++++++++++++++++ 7 files changed, 206 insertions(+), 192 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/k/KrosDefenseContractor.java create mode 100644 Mage/src/main/java/mage/abilities/common/PutCounterOnCreatureTriggeredAbility.java diff --git a/Mage.Sets/src/mage/cards/g/GenerousPatron.java b/Mage.Sets/src/mage/cards/g/GenerousPatron.java index 880a231b0d5..92037434730 100644 --- a/Mage.Sets/src/mage/cards/g/GenerousPatron.java +++ b/Mage.Sets/src/mage/cards/g/GenerousPatron.java @@ -1,17 +1,16 @@ package mage.cards.g; import mage.MageInt; -import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.keyword.SupportAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Zone; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.permanent.Permanent; +import mage.constants.TargetController; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.abilities.common.PutCounterOnCreatureTriggeredAbility; import java.util.UUID; @@ -20,6 +19,13 @@ import java.util.UUID; */ public final class GenerousPatron extends CardImpl { + private static final FilterPermanent filter + = new FilterCreaturePermanent("creature you don't control"); + + static { + filter.add(TargetController.NOT_YOU.getControllerPredicate()); + } + public GenerousPatron(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}"); @@ -32,7 +38,7 @@ public final class GenerousPatron extends CardImpl { this.addAbility(new SupportAbility(this, 2)); // Whenever you put one or more counters on a creature you don't control, draw a card. - this.addAbility(new GenerousPatronTriggeredAbility()); + this.addAbility(new PutCounterOnCreatureTriggeredAbility(new DrawCardSourceControllerEffect(1), filter)); } private GenerousPatron(final GenerousPatron card) { @@ -44,43 +50,3 @@ public final class GenerousPatron extends CardImpl { return new GenerousPatron(this); } } - -class GenerousPatronTriggeredAbility extends TriggeredAbilityImpl { - - GenerousPatronTriggeredAbility() { - super(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), false); - } - - private GenerousPatronTriggeredAbility(GenerousPatronTriggeredAbility ability) { - super(ability); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.COUNTERS_ADDED; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (!isControlledBy(event.getPlayerId())) { - return false; - } - Permanent permanent = game.getPermanentOrLKIBattlefield(event.getTargetId()); - if (permanent == null) { - permanent = game.getPermanentEntering(event.getTargetId()); - } - return permanent != null - && permanent.isCreature(game) - && !permanent.isControlledBy(getControllerId()); - } - - @Override - public GenerousPatronTriggeredAbility copy() { - return new GenerousPatronTriggeredAbility(this); - } - - @Override - public String getTriggerPhrase() { - return "Whenever you put one or more counters on a creature you don't control, " ; - } -} diff --git a/Mage.Sets/src/mage/cards/h/HapatraVizierOfPoisons.java b/Mage.Sets/src/mage/cards/h/HapatraVizierOfPoisons.java index a0d0595ae88..f800ca2855e 100644 --- a/Mage.Sets/src/mage/cards/h/HapatraVizierOfPoisons.java +++ b/Mage.Sets/src/mage/cards/h/HapatraVizierOfPoisons.java @@ -1,10 +1,9 @@ - package mage.cards.h; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; +import mage.abilities.common.PutCounterOnCreatureTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.counter.AddCountersTargetEffect; import mage.cards.CardImpl; @@ -12,11 +11,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.SuperType; -import mage.constants.Zone; import mage.counters.CounterType; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.permanent.Permanent; import mage.game.permanent.token.DeathtouchSnakeToken; import mage.target.common.TargetCreaturePermanent; @@ -42,7 +37,7 @@ public final class HapatraVizierOfPoisons extends CardImpl { this.addAbility(ability); // Whenever you put one or more -1/-1 counters on a creature, create a 1/1 green Snake creature token with deathtouch. - this.addAbility(new HapatraVizierOfPoisonsTriggeredAbility()); + this.addAbility(new PutCounterOnCreatureTriggeredAbility(new CreateTokenEffect(new DeathtouchSnakeToken()), CounterType.M1M1.createInstance())); } private HapatraVizierOfPoisons(final HapatraVizierOfPoisons card) { @@ -54,43 +49,3 @@ public final class HapatraVizierOfPoisons extends CardImpl { return new HapatraVizierOfPoisons(this); } } - -class HapatraVizierOfPoisonsTriggeredAbility extends TriggeredAbilityImpl { - - HapatraVizierOfPoisonsTriggeredAbility() { - super(Zone.BATTLEFIELD, new CreateTokenEffect(new DeathtouchSnakeToken()), false); - } - - private HapatraVizierOfPoisonsTriggeredAbility(HapatraVizierOfPoisonsTriggeredAbility ability) { - super(ability); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.COUNTERS_ADDED; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (!event.getData().equals(CounterType.M1M1.getName()) - || !isControlledBy(event.getPlayerId())) { - return false; - } - Permanent permanent = game.getPermanentOrLKIBattlefield(event.getTargetId()); - if (permanent == null) { - permanent = game.getPermanentEntering(event.getTargetId()); - } - return permanent != null && permanent.isCreature(game); - - } - - @Override - public HapatraVizierOfPoisonsTriggeredAbility copy() { - return new HapatraVizierOfPoisonsTriggeredAbility(this); - } - - @Override - public String getTriggerPhrase() { - return "Whenever you put one or more -1/-1 counters on a creature, " ; - } -} diff --git a/Mage.Sets/src/mage/cards/k/KrosDefenseContractor.java b/Mage.Sets/src/mage/cards/k/KrosDefenseContractor.java new file mode 100644 index 00000000000..6c221c40cc6 --- /dev/null +++ b/Mage.Sets/src/mage/cards/k/KrosDefenseContractor.java @@ -0,0 +1,95 @@ +package mage.cards.k; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.PutCounterOnCreatureTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.combat.GoadTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.counters.CounterType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.common.TargetOpponentsCreaturePermanent; +import mage.target.targetpointer.FixedTarget; + +import java.util.UUID; + +/** + * @author PurpleCrowbar + */ +public final class KrosDefenseContractor extends CardImpl { + + private static final FilterPermanent filter + = new FilterCreaturePermanent("creature you don't control"); + + static { + filter.add(TargetController.NOT_YOU.getControllerPredicate()); + } + + public KrosDefenseContractor(UUID ownerID, CardSetInfo setInfo) { + super(ownerID, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}{W}{U}"); + + addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.CAT); + this.subtype.add(SubType.ADVISOR); + this.power = new MageInt(2); + this.toughness = new MageInt(4); + + // At the beginning of your upkeep, put a shield counter on target creature an opponent controls. + Ability ability = new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, + new AddCountersTargetEffect(CounterType.SHIELD.createInstance()), TargetController.YOU, false); + ability.addTarget(new TargetOpponentsCreaturePermanent()); + this.addAbility(ability); + + // Whenever you put one or more counters on a creature you don't control, tap that creature and goad it. It gains trample until your next turn. + this.addAbility(new PutCounterOnCreatureTriggeredAbility(new KrosDefenseContractorEffect(), null, filter, true)); + } + + private KrosDefenseContractor(final KrosDefenseContractor card) { + super(card); + } + + @Override + public KrosDefenseContractor copy() { + return new KrosDefenseContractor(this); + } +} + +class KrosDefenseContractorEffect extends OneShotEffect { + + KrosDefenseContractorEffect() { + super(Outcome.BoostCreature); + this.staticText = "tap that creature and goad it. It gains trample until your next turn."; + } + + private KrosDefenseContractorEffect(final KrosDefenseContractorEffect effect) { + super(effect); + } + + @Override + public KrosDefenseContractorEffect copy() { + return new KrosDefenseContractorEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent creature = getTargetPointer().getFirstTargetPermanentOrLKI(game, source); + if (creature == null) { + return false; + } + creature.tap(source, game); + game.addEffect(new GainAbilityTargetEffect( + TrampleAbility.getInstance(), Duration.UntilYourNextTurn + ).setTargetPointer(new FixedTarget(creature, game)), source); + game.addEffect(new GoadTargetEffect().setTargetPointer(new FixedTarget(creature, game)), source); + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/n/NestOfScarabs.java b/Mage.Sets/src/mage/cards/n/NestOfScarabs.java index c759de2aa8a..66c39c6f280 100644 --- a/Mage.Sets/src/mage/cards/n/NestOfScarabs.java +++ b/Mage.Sets/src/mage/cards/n/NestOfScarabs.java @@ -1,16 +1,12 @@ package mage.cards.n; -import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.PutCounterOnCreatureTriggeredAbility; import mage.abilities.dynamicvalue.common.EffectKeyValue; import mage.abilities.effects.common.CreateTokenEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Zone; import mage.counters.CounterType; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.permanent.Permanent; import mage.game.permanent.token.NestOfScarabsBlackInsectToken; import java.util.UUID; @@ -23,9 +19,9 @@ public final class NestOfScarabs extends CardImpl { public NestOfScarabs(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{B}"); - // Whenever you put one or more -1/-1 counters on a creature, create that many 1/1 black Insect tokens. - this.addAbility(new NestOfScarabsTriggeredAbility()); - + // Whenever you put one or more -1/-1 counters on a creature, create that many 1/1 black Insect creature tokens. + this.addAbility(new PutCounterOnCreatureTriggeredAbility(new CreateTokenEffect(new NestOfScarabsBlackInsectToken(), new EffectKeyValue("countersAdded")) + .setText("create that many 1/1 black Insect creature tokens"), CounterType.M1M1.createInstance())); } private NestOfScarabs(final NestOfScarabs card) { @@ -37,46 +33,3 @@ public final class NestOfScarabs extends CardImpl { return new NestOfScarabs(this); } } - -class NestOfScarabsTriggeredAbility extends TriggeredAbilityImpl { - - NestOfScarabsTriggeredAbility() { - super(Zone.BATTLEFIELD, new CreateTokenEffect(new NestOfScarabsBlackInsectToken(), new EffectKeyValue("countersAdded"))); - } - - NestOfScarabsTriggeredAbility(final NestOfScarabsTriggeredAbility ability) { - super(ability); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.COUNTERS_ADDED; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - boolean weAreDoingIt = isControlledBy(event.getPlayerId()); - boolean isM1M1Counters = event.getData().equals(CounterType.M1M1.getName()); - if (weAreDoingIt && isM1M1Counters && event.getAmount() > 0) { - Permanent permanent = game.getPermanentOrLKIBattlefield(event.getTargetId()); - if (permanent == null) { - permanent = game.getPermanentEntering(event.getTargetId()); - } - if (permanent != null && permanent.isCreature(game)) { - getEffects().setValue("countersAdded", event.getAmount()); - return true; - } - } - return false; - } - - @Override - public NestOfScarabsTriggeredAbility copy() { - return new NestOfScarabsTriggeredAbility(this); - } - - @Override - public String getRule() { - return "Whenever you put one or more -1/-1 counters on a creature, create that many 1/1 black Insect tokens."; - } -} diff --git a/Mage.Sets/src/mage/cards/o/ObeliskSpider.java b/Mage.Sets/src/mage/cards/o/ObeliskSpider.java index a09641bb21a..c9982c40480 100644 --- a/Mage.Sets/src/mage/cards/o/ObeliskSpider.java +++ b/Mage.Sets/src/mage/cards/o/ObeliskSpider.java @@ -1,11 +1,10 @@ - package mage.cards.o; import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.DealsDamageToACreatureTriggeredAbility; +import mage.abilities.common.PutCounterOnCreatureTriggeredAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.LoseLifeOpponentsEffect; @@ -15,11 +14,7 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Zone; import mage.counters.CounterType; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.permanent.Permanent; /** * @@ -41,7 +36,7 @@ public final class ObeliskSpider extends CardImpl { this.addAbility(new DealsDamageToACreatureTriggeredAbility(new AddCountersTargetEffect(CounterType.M1M1.createInstance(1)), true, false, true)); // Whenever you put one or more -1/-1 counters on a creature, each opponent loses 1 life and you gain 1 life. - Ability ability = new ObeliskSpiderTriggeredAbility(new LoseLifeOpponentsEffect(1), false); + Ability ability = new PutCounterOnCreatureTriggeredAbility(new LoseLifeOpponentsEffect(1), CounterType.M1M1.createInstance()); Effect effect = new GainLifeEffect(1); effect.setText("and you gain 1 life"); ability.addEffect(effect); @@ -57,44 +52,3 @@ public final class ObeliskSpider extends CardImpl { return new ObeliskSpider(this); } } - -class ObeliskSpiderTriggeredAbility extends TriggeredAbilityImpl { - - public ObeliskSpiderTriggeredAbility(Effect effect, boolean optional) { - super(Zone.BATTLEFIELD, effect, optional); - } - - public ObeliskSpiderTriggeredAbility(ObeliskSpiderTriggeredAbility ability) { - super(ability); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.COUNTERS_ADDED; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (event.getData().equals(CounterType.M1M1.getName()) - && isControlledBy(event.getPlayerId())) { - Permanent permanent = game.getPermanentOrLKIBattlefield(event.getTargetId()); - if (permanent == null) { - permanent = game.getPermanentEntering(event.getTargetId()); - } - return (permanent != null - && permanent.isCreature(game)); - } - return false; - - } - - @Override - public ObeliskSpiderTriggeredAbility copy() { - return new ObeliskSpiderTriggeredAbility(this); - } - - @Override - public String getTriggerPhrase() { - return "Whenever you put one or more -1/-1 counters on a creature, " ; - } -} diff --git a/Mage.Sets/src/mage/sets/NewCapennaCommander.java b/Mage.Sets/src/mage/sets/NewCapennaCommander.java index 60b87f7444e..be8c0bba6a1 100644 --- a/Mage.Sets/src/mage/sets/NewCapennaCommander.java +++ b/Mage.Sets/src/mage/sets/NewCapennaCommander.java @@ -181,6 +181,8 @@ public final class NewCapennaCommander extends ExpansionSet { cards.add(new SetCardInfo("Kitt Kanto, Mayhem Diva", 4, Rarity.MYTHIC, mage.cards.k.KittKantoMayhemDiva.class)); cards.add(new SetCardInfo("Kodama's Reach", 298, Rarity.COMMON, mage.cards.k.KodamasReach.class)); cards.add(new SetCardInfo("Kresh the Bloodbraided", 345, Rarity.MYTHIC, mage.cards.k.KreshTheBloodbraided.class)); + cards.add(new SetCardInfo("Kros, Defense Contractor", 7, Rarity.MYTHIC, mage.cards.k.KrosDefenseContractor.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Kros, Defense Contractor", 105, Rarity.MYTHIC, mage.cards.k.KrosDefenseContractor.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Leafkin Druid", 299, Rarity.COMMON, mage.cards.l.LeafkinDruid.class)); cards.add(new SetCardInfo("Life Insurance", 74, Rarity.RARE, mage.cards.l.LifeInsurance.class)); cards.add(new SetCardInfo("Life of the Party", 48, Rarity.RARE, mage.cards.l.LifeOfTheParty.class)); diff --git a/Mage/src/main/java/mage/abilities/common/PutCounterOnCreatureTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/PutCounterOnCreatureTriggeredAbility.java new file mode 100644 index 00000000000..3023d8d0633 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/common/PutCounterOnCreatureTriggeredAbility.java @@ -0,0 +1,89 @@ +package mage.abilities.common; + +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.Effect; +import mage.constants.Zone; +import mage.counters.Counter; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.target.targetpointer.FixedTarget; + +/** + * "Whenever you put one or more counters on a creature " triggered ability + * + * @author PurpleCrowbar + */ +public class PutCounterOnCreatureTriggeredAbility extends TriggeredAbilityImpl { + + private final Counter counterType; // when null, any counter type is accepted + private final FilterPermanent filter; + private final boolean setTargetPointer; + + public PutCounterOnCreatureTriggeredAbility(Effect effect) { + this(effect, (Counter) null); + } + + public PutCounterOnCreatureTriggeredAbility(Effect effect, Counter counter) { + this(effect, counter, new FilterCreaturePermanent()); + } + + public PutCounterOnCreatureTriggeredAbility(Effect effect, FilterPermanent filter) { + this(effect, null, filter); + } + + public PutCounterOnCreatureTriggeredAbility(Effect effect, Counter counter, FilterPermanent filter) { + this(effect, counter, filter, false); + } + + public PutCounterOnCreatureTriggeredAbility(Effect effect, Counter counter, FilterPermanent filter, boolean setTargetPointer) { + super(Zone.BATTLEFIELD, effect); + this.counterType = counter; + this.filter = filter; + this.setTargetPointer = setTargetPointer; + if (counter == null) { + setTriggerPhrase("Whenever you put one or more counters on a " + filter.getMessage() + ", "); + } + else { + setTriggerPhrase("Whenever you put one or more " + counter.getName() + " counters on a " + filter.getMessage() + ", "); + } + } + + public PutCounterOnCreatureTriggeredAbility(final PutCounterOnCreatureTriggeredAbility ability) { + super(ability); + this.counterType = ability.counterType; + this.filter = ability.filter; + this.setTargetPointer = ability.setTargetPointer; + } + + @Override + public PutCounterOnCreatureTriggeredAbility copy() { + return new PutCounterOnCreatureTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.COUNTERS_ADDED; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (!isControlledBy(event.getPlayerId())) { + return false; + } + Permanent permanent = game.getPermanentOrLKIBattlefield(event.getTargetId()); + if (permanent == null || !filter.match(permanent, controllerId, this, game)) { + return false; + } + if (counterType != null && !event.getData().equals(counterType.getName())) { + return false; + } + if (setTargetPointer) { + getEffects().setTargetPointer(new FixedTarget(event.getTargetId(), game)); + } + getEffects().setValue("countersAdded", event.getAmount()); + return true; + } +}