From 602e622c7df1c9ac99bb8f7820a1840c1a025812 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Wed, 25 Jan 2023 09:13:10 -0500 Subject: [PATCH] [ONE] Implement Infectious Bite --- .../src/mage/cards/d/DaxosTheReturned.java | 2 +- .../src/mage/cards/e/EzuriClawOfProgress.java | 2 +- Mage.Sets/src/mage/cards/i/IchorRats.java | 38 +------ .../src/mage/cards/i/InfectiousBite.java | 38 +++++++ .../mage/cards/k/KalemneDiscipleOfIroas.java | 2 +- .../src/mage/cards/k/KelsienThePlague.java | 2 +- .../src/mage/cards/m/MerenOfClanNelToth.java | 2 +- .../src/mage/cards/m/MizzixOfTheIzmagnus.java | 2 +- .../src/mage/cards/p/PhyrexianVatmother.java | 47 ++------ .../src/mage/cards/r/RelicPutrescence.java | 12 +- .../src/mage/sets/PhyrexiaAllWillBeOne.java | 1 + .../counter/AddCountersControllerEffect.java | 29 +---- .../counter/AddPoisonCounterAllEffect.java | 105 ++++++++++++++++++ 13 files changed, 177 insertions(+), 105 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/i/InfectiousBite.java create mode 100644 Mage/src/main/java/mage/abilities/effects/common/counter/AddPoisonCounterAllEffect.java diff --git a/Mage.Sets/src/mage/cards/d/DaxosTheReturned.java b/Mage.Sets/src/mage/cards/d/DaxosTheReturned.java index abb525d1bd..3cffc64b0b 100644 --- a/Mage.Sets/src/mage/cards/d/DaxosTheReturned.java +++ b/Mage.Sets/src/mage/cards/d/DaxosTheReturned.java @@ -38,7 +38,7 @@ public final class DaxosTheReturned extends CardImpl { this.toughness = new MageInt(2); // Whenever you cast an enchantment spell, you get an experience counter. - Effect effect = new AddCountersControllerEffect(CounterType.EXPERIENCE.createInstance(1), false); + Effect effect = new AddCountersControllerEffect(CounterType.EXPERIENCE.createInstance(1)); effect.setText("you get an experience counter"); Ability ability = new SpellCastControllerTriggeredAbility(effect, filter, false); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/e/EzuriClawOfProgress.java b/Mage.Sets/src/mage/cards/e/EzuriClawOfProgress.java index 445c449493..430d6b5fdb 100644 --- a/Mage.Sets/src/mage/cards/e/EzuriClawOfProgress.java +++ b/Mage.Sets/src/mage/cards/e/EzuriClawOfProgress.java @@ -47,7 +47,7 @@ public final class EzuriClawOfProgress extends CardImpl { // Whenever a creature with power 2 or less enters the battlefield under your control, you get an experience counter. this.addAbility(new EntersBattlefieldAllTriggeredAbility(Zone.BATTLEFIELD, new AddCountersControllerEffect( - CounterType.EXPERIENCE.createInstance(1), false), filter, false, rule, true)); + CounterType.EXPERIENCE.createInstance(1)), filter, false, rule, true)); // At the beginning of combat on your turn, put X +1/+1 counters on another target creature you control, where X is the number of experience counters you have. Ability ability = new BeginningOfCombatTriggeredAbility(new EzuriClawOfProgressEffect(), TargetController.YOU, false); diff --git a/Mage.Sets/src/mage/cards/i/IchorRats.java b/Mage.Sets/src/mage/cards/i/IchorRats.java index 6c7fcb39b3..eaec41dbf6 100644 --- a/Mage.Sets/src/mage/cards/i/IchorRats.java +++ b/Mage.Sets/src/mage/cards/i/IchorRats.java @@ -1,23 +1,24 @@ - package mage.cards.i; import java.util.UUID; + import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.counter.AddPoisonCounterAllEffect; import mage.abilities.keyword.InfectAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Outcome; +import mage.constants.TargetController; import mage.counters.CounterType; import mage.game.Game; import mage.players.Player; /** - * * @author Loki */ public final class IchorRats extends CardImpl { @@ -30,7 +31,9 @@ public final class IchorRats extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(1); this.addAbility(InfectAbility.getInstance()); - this.addAbility(new EntersBattlefieldTriggeredAbility(new IchorRatsEffect(), false)); + this.addAbility(new EntersBattlefieldTriggeredAbility( + new AddPoisonCounterAllEffect(TargetController.EACH_PLAYER), false + )); } private IchorRats(final IchorRats card) { @@ -43,32 +46,3 @@ public final class IchorRats extends CardImpl { } } - -class IchorRatsEffect extends OneShotEffect { - - public IchorRatsEffect() { - super(Outcome.Damage); - staticText = "each player gets a poison counter"; - } - - public IchorRatsEffect(final IchorRatsEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - for (UUID playerId : game.getState().getPlayerList(source.getControllerId())) { - Player player = game.getPlayer(playerId); - if (player != null) { - player.addCounters(CounterType.POISON.createInstance(), source.getControllerId(), source, game); - } - } - return true; - } - - @Override - public IchorRatsEffect copy() { - return new IchorRatsEffect(this); - } - -} diff --git a/Mage.Sets/src/mage/cards/i/InfectiousBite.java b/Mage.Sets/src/mage/cards/i/InfectiousBite.java new file mode 100644 index 0000000000..4e1cd20ec3 --- /dev/null +++ b/Mage.Sets/src/mage/cards/i/InfectiousBite.java @@ -0,0 +1,38 @@ +package mage.cards.i; + +import java.util.UUID; + +import mage.abilities.effects.common.DamageWithPowerFromOneToAnotherTargetEffect; +import mage.abilities.effects.common.counter.AddPoisonCounterAllEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.TargetController; +import mage.filter.StaticFilters; +import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * @author TheElk801 + */ +public final class InfectiousBite extends CardImpl { + + public InfectiousBite(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{G}"); + + // Target creature you control deals damage equal to its power to target creature you don't control. Each opponent gets a poison counter. + this.getSpellAbility().addEffect(new DamageWithPowerFromOneToAnotherTargetEffect()); + this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); + this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); + this.getSpellAbility().addEffect(new AddPoisonCounterAllEffect(TargetController.OPPONENT)); + } + + private InfectiousBite(final InfectiousBite card) { + super(card); + } + + @Override + public InfectiousBite copy() { + return new InfectiousBite(this); + } +} diff --git a/Mage.Sets/src/mage/cards/k/KalemneDiscipleOfIroas.java b/Mage.Sets/src/mage/cards/k/KalemneDiscipleOfIroas.java index 3c1741a855..1ea7a1b6dc 100644 --- a/Mage.Sets/src/mage/cards/k/KalemneDiscipleOfIroas.java +++ b/Mage.Sets/src/mage/cards/k/KalemneDiscipleOfIroas.java @@ -54,7 +54,7 @@ public final class KalemneDiscipleOfIroas extends CardImpl { this.addAbility(VigilanceAbility.getInstance()); // Whenever you cast a creature spell with converted mana cost 5 or greater, you get an experience counter. - Effect effect = new AddCountersControllerEffect(CounterType.EXPERIENCE.createInstance(1), false); + Effect effect = new AddCountersControllerEffect(CounterType.EXPERIENCE.createInstance(1)); effect.setText("you get an experience counter"); Ability ability = new SpellCastControllerTriggeredAbility(effect, filterSpell, false); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/k/KelsienThePlague.java b/Mage.Sets/src/mage/cards/k/KelsienThePlague.java index b0b34df61d..3a0b1b7923 100644 --- a/Mage.Sets/src/mage/cards/k/KelsienThePlague.java +++ b/Mage.Sets/src/mage/cards/k/KelsienThePlague.java @@ -53,7 +53,7 @@ public final class KelsienThePlague extends CardImpl { // {T}: Kelsien deals 1 damage to target creature you don't control. When that creature dies this turn, you get an experience counter. Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(1), new TapSourceCost()); ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new WhenTargetDiesDelayedTriggeredAbility( - new AddCountersControllerEffect(CounterType.EXPERIENCE.createInstance(), false) + new AddCountersControllerEffect(CounterType.EXPERIENCE.createInstance()) ))); ability.addTarget(new TargetPermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/m/MerenOfClanNelToth.java b/Mage.Sets/src/mage/cards/m/MerenOfClanNelToth.java index 8b0bf5cfe6..07dea86b44 100644 --- a/Mage.Sets/src/mage/cards/m/MerenOfClanNelToth.java +++ b/Mage.Sets/src/mage/cards/m/MerenOfClanNelToth.java @@ -43,7 +43,7 @@ public final class MerenOfClanNelToth extends CardImpl { // Whenever another creature you control dies, you get an experience counter. this.addAbility(new DiesCreatureTriggeredAbility(new AddCountersControllerEffect( - CounterType.EXPERIENCE.createInstance(1), false + CounterType.EXPERIENCE.createInstance(1) ).setText("you get an experience counter"), false, filter)); // At the beginning of your end step, choose target creature card in your graveyard. diff --git a/Mage.Sets/src/mage/cards/m/MizzixOfTheIzmagnus.java b/Mage.Sets/src/mage/cards/m/MizzixOfTheIzmagnus.java index 93dc1c0386..6237a53da4 100644 --- a/Mage.Sets/src/mage/cards/m/MizzixOfTheIzmagnus.java +++ b/Mage.Sets/src/mage/cards/m/MizzixOfTheIzmagnus.java @@ -44,7 +44,7 @@ public final class MizzixOfTheIzmagnus extends CardImpl { // Whenever you cast an instant or sorcery spell with converted mana cost greater than the number of experience counters you have, you get an experience counter. this.addAbility(new SpellCastControllerTriggeredAbility( - new AddCountersControllerEffect(CounterType.EXPERIENCE.createInstance(1), false), filter, false)); + new AddCountersControllerEffect(CounterType.EXPERIENCE.createInstance(1)), filter, false)); // Instant and sorcery spells you cast cost {1} less to cast for each experience counter you have. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new MizzixOfTheIzmagnusCostReductionEffect())); diff --git a/Mage.Sets/src/mage/cards/p/PhyrexianVatmother.java b/Mage.Sets/src/mage/cards/p/PhyrexianVatmother.java index b1f88a2b7e..7e54e67cf3 100644 --- a/Mage.Sets/src/mage/cards/p/PhyrexianVatmother.java +++ b/Mage.Sets/src/mage/cards/p/PhyrexianVatmother.java @@ -1,41 +1,44 @@ - - package mage.cards.p; import java.util.UUID; + import mage.MageInt; import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.OnEventTriggeredAbility; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.counter.AddPoisonCounterAllEffect; import mage.abilities.keyword.InfectAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Outcome; +import mage.constants.TargetController; import mage.counters.CounterType; import mage.game.Game; import mage.game.events.GameEvent.EventType; import mage.players.Player; /** - * * @author Viserion */ public final class PhyrexianVatmother extends CardImpl { - public PhyrexianVatmother (UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{B}{B}"); + public PhyrexianVatmother(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}{B}"); this.subtype.add(SubType.PHYREXIAN); this.subtype.add(SubType.HORROR); this.power = new MageInt(4); this.toughness = new MageInt(5); this.addAbility(InfectAbility.getInstance()); - this.addAbility(new OnEventTriggeredAbility(EventType.UPKEEP_STEP_PRE, "beginning of your upkeep", new PoisonControllerEffect())); + this.addAbility(new BeginningOfUpkeepTriggeredAbility( + new AddPoisonCounterAllEffect(TargetController.YOU), TargetController.YOU, false + )); } - public PhyrexianVatmother (final PhyrexianVatmother card) { + public PhyrexianVatmother(final PhyrexianVatmother card) { super(card); } @@ -43,34 +46,4 @@ public final class PhyrexianVatmother extends CardImpl { public PhyrexianVatmother copy() { return new PhyrexianVatmother(this); } - -} - -class PoisonControllerEffect extends OneShotEffect { - - public PoisonControllerEffect() { - super(Outcome.Damage); - staticText = "you get a poison counter"; - - } - - public PoisonControllerEffect(final PoisonControllerEffect effect) { - super(effect); - } - - @Override - public PoisonControllerEffect copy() { - return new PoisonControllerEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - if (player != null) { - player.addCounters(CounterType.POISON.createInstance(), source.getControllerId(), source, game); - return true; - } - return false; - } - } diff --git a/Mage.Sets/src/mage/cards/r/RelicPutrescence.java b/Mage.Sets/src/mage/cards/r/RelicPutrescence.java index e85110386d..a73e05a84e 100644 --- a/Mage.Sets/src/mage/cards/r/RelicPutrescence.java +++ b/Mage.Sets/src/mage/cards/r/RelicPutrescence.java @@ -1,28 +1,30 @@ package mage.cards.r; import java.util.UUID; + import mage.abilities.Ability; import mage.abilities.common.BecomesTappedAttachedTriggeredAbility; import mage.abilities.effects.common.AttachEffect; import mage.abilities.effects.common.counter.AddCountersControllerEffect; +import mage.abilities.effects.common.counter.AddPoisonCounterAllEffect; import mage.abilities.keyword.EnchantAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Outcome; +import mage.constants.TargetController; import mage.counters.CounterType; import mage.target.TargetPermanent; import mage.target.common.TargetArtifactPermanent; /** - * * @author nantuko */ public final class RelicPutrescence extends CardImpl { - public RelicPutrescence (UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{B}"); + public RelicPutrescence(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{B}"); this.subtype.add(SubType.AURA); TargetPermanent auraTarget = new TargetArtifactPermanent(); @@ -33,12 +35,12 @@ public final class RelicPutrescence extends CardImpl { // Whenever enchanted artifact becomes tapped, its controller gets a poison counter. this.addAbility(new BecomesTappedAttachedTriggeredAbility( - new AddCountersControllerEffect(CounterType.POISON.createInstance(), true), + new AddPoisonCounterAllEffect(TargetController.CONTROLLER_ATTACHED_TO), "enchanted artifact" )); } - public RelicPutrescence (final RelicPutrescence card) { + public RelicPutrescence(final RelicPutrescence card) { super(card); } diff --git a/Mage.Sets/src/mage/sets/PhyrexiaAllWillBeOne.java b/Mage.Sets/src/mage/sets/PhyrexiaAllWillBeOne.java index e311b5f183..69e3e8c018 100644 --- a/Mage.Sets/src/mage/sets/PhyrexiaAllWillBeOne.java +++ b/Mage.Sets/src/mage/sets/PhyrexiaAllWillBeOne.java @@ -60,6 +60,7 @@ public final class PhyrexiaAllWillBeOne extends ExpansionSet { cards.add(new SetCardInfo("Hexgold Halberd", 136, Rarity.UNCOMMON, mage.cards.h.HexgoldHalberd.class)); cards.add(new SetCardInfo("Hexgold Slash", 137, Rarity.COMMON, mage.cards.h.HexgoldSlash.class)); cards.add(new SetCardInfo("Incisor Glider", 15, Rarity.COMMON, mage.cards.i.IncisorGlider.class)); + cards.add(new SetCardInfo("Infectious Bite", 172, Rarity.UNCOMMON, mage.cards.i.InfectiousBite.class)); cards.add(new SetCardInfo("Infested Fleshcutter", 17, Rarity.UNCOMMON, mage.cards.i.InfestedFleshcutter.class)); cards.add(new SetCardInfo("Island", 273, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Jawbone Duelist", 18, Rarity.UNCOMMON, mage.cards.j.JawboneDuelist.class)); diff --git a/Mage/src/main/java/mage/abilities/effects/common/counter/AddCountersControllerEffect.java b/Mage/src/main/java/mage/abilities/effects/common/counter/AddCountersControllerEffect.java index 3b5d6fbc7d..270d1b8c38 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/counter/AddCountersControllerEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/counter/AddCountersControllerEffect.java @@ -16,19 +16,14 @@ import java.util.UUID; public class AddCountersControllerEffect extends OneShotEffect { private Counter counter; - private final boolean enchantedEquipped; /** - * @param counter Counter to add. Includes type and amount. - * @param enchantedEquipped If true, not source controller will get the - * counter, but the permanent's controller that the source permanent - * enchants or equippes. + * @param counter Counter to add. Includes type and amount. */ - public AddCountersControllerEffect(Counter counter, boolean enchantedEquipped) { + public AddCountersControllerEffect(Counter counter) { super(Outcome.Benefit); this.counter = counter.copy(); - this.enchantedEquipped = enchantedEquipped; - staticText = (enchantedEquipped ? "its controller gets " : "you get ") + counter.getDescription(); + staticText = "you get" + counter.getDescription(); } public AddCountersControllerEffect(final AddCountersControllerEffect effect) { @@ -36,27 +31,11 @@ public class AddCountersControllerEffect extends OneShotEffect { if (effect.counter != null) { this.counter = effect.counter.copy(); } - this.enchantedEquipped = effect.enchantedEquipped; } @Override public boolean apply(Game game, Ability source) { - UUID uuid = source.getControllerId(); - if (this.enchantedEquipped) { - Permanent enchantment = game.getPermanent(source.getSourceId()); - if (enchantment != null && enchantment.getAttachedTo() != null) { - UUID eUuid = enchantment.getAttachedTo(); - Permanent permanent = game.getPermanent(eUuid); - if (permanent != null) { - uuid = permanent.getControllerId(); - } else { - return false; - } - } else { - return false; - } - } - Player player = game.getPlayer(uuid); + Player player = game.getPlayer(source.getControllerId()); if (player != null) { player.addCounters(counter, source.getControllerId(), source, game); return true; diff --git a/Mage/src/main/java/mage/abilities/effects/common/counter/AddPoisonCounterAllEffect.java b/Mage/src/main/java/mage/abilities/effects/common/counter/AddPoisonCounterAllEffect.java new file mode 100644 index 0000000000..844daafbcb --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/counter/AddPoisonCounterAllEffect.java @@ -0,0 +1,105 @@ +package mage.abilities.effects.common.counter; + +import mage.abilities.Ability; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.constants.Outcome; +import mage.constants.TargetController; +import mage.counters.CounterType; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.util.CardUtil; + +import java.util.*; + +/** + * @author TheElk801 + */ +public class AddPoisonCounterAllEffect extends OneShotEffect { + + private final int amount; + private final TargetController targetController; + + public AddPoisonCounterAllEffect(TargetController targetController) { + this(1, targetController); + } + + public AddPoisonCounterAllEffect(int amount, TargetController targetController) { + super(Outcome.Benefit); + this.amount = amount; + this.targetController = targetController; + staticText = makeText(); + } + + private AddPoisonCounterAllEffect(final AddPoisonCounterAllEffect effect) { + super(effect); + this.amount = effect.amount; + this.targetController = effect.targetController; + } + + @Override + public AddPoisonCounterAllEffect copy() { + return new AddPoisonCounterAllEffect(this); + } + + private Collection getPlayers(Game game, Ability source) { + switch (targetController) { + case OPPONENT: + return game.getOpponents(source.getControllerId()); + case EACH_PLAYER: + case ANY: + return game.getState().getPlayersInRange(source.getControllerId(), game); + case YOU: + return Arrays.asList(source.getControllerId()); + case CONTROLLER_ATTACHED_TO: + List list = new ArrayList<>(); + Optional.ofNullable(source.getSourcePermanentOrLKI(game)) + .filter(Objects::nonNull) + .map(Permanent::getAttachedTo) + .map(game::getControllerId) + .filter(Objects::nonNull) + .ifPresent(list::add); + return list; + default: + throw new UnsupportedOperationException(targetController + " not supported"); + } + } + + @Override + public boolean apply(Game game, Ability source) { + for (UUID playerId : getPlayers(game, source)) { + Player player = game.getPlayer(playerId); + if (player != null) { + player.addCounters(CounterType.POISON.createInstance(amount), source.getControllerId(), source, game); + } + } + return true; + } + + public String makeText() { + StringBuilder sb = new StringBuilder(); + switch (targetController) { + case OPPONENT: + sb.append("each opponent gets"); + break; + case ANY: + case EACH_PLAYER: + sb.append("each player gets"); + break; + case YOU: + sb.append("you get"); + break; + case CONTROLLER_ATTACHED_TO: + sb.append("its controller gets"); + break; + default: + throw new UnsupportedOperationException(targetController + " not supported"); + } + sb.append(' ' + CardUtil.numberToText(amount, "a") + " poison counter"); + if (amount > 1) { + sb.append('s'); + } + return sb.toString(); + } +}