diff --git a/Mage.Sets/src/mage/cards/b/BloodsporeThrinax.java b/Mage.Sets/src/mage/cards/b/BloodsporeThrinax.java index a2ca0660869..7705c56ffca 100644 --- a/Mage.Sets/src/mage/cards/b/BloodsporeThrinax.java +++ b/Mage.Sets/src/mage/cards/b/BloodsporeThrinax.java @@ -1,12 +1,10 @@ package mage.cards.b; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ReplacementEffectImpl; -import mage.abilities.effects.common.DevourEffect; import mage.abilities.keyword.DevourAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -17,6 +15,8 @@ import mage.game.events.EntersTheBattlefieldEvent; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; +import java.util.UUID; + /** * * @author fireshoes @@ -30,7 +30,7 @@ public final class BloodsporeThrinax extends CardImpl { this.toughness = new MageInt(2); // Devour 1 - this.addAbility(new DevourAbility(DevourEffect.DevourFactor.Devour1)); + this.addAbility(new DevourAbility(1)); // Each other creature you control enters the battlefield with an additional X +1/+1 counters on it, where X is the number of +1/+1 counters on Bloodspire Thrinax. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BloodsporeThrinaxEntersBattlefieldEffect())); diff --git a/Mage.Sets/src/mage/cards/c/CalderaHellion.java b/Mage.Sets/src/mage/cards/c/CalderaHellion.java index 0cafd8cbc81..39f35670e88 100644 --- a/Mage.Sets/src/mage/cards/c/CalderaHellion.java +++ b/Mage.Sets/src/mage/cards/c/CalderaHellion.java @@ -1,11 +1,9 @@ package mage.cards.c; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.effects.common.DamageAllEffect; -import mage.abilities.effects.common.DevourEffect.DevourFactor; import mage.abilities.keyword.DevourAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -13,6 +11,8 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; +import java.util.UUID; + /** * * @author LevelX2 @@ -27,7 +27,7 @@ public final class CalderaHellion extends CardImpl { this.toughness = new MageInt(3); // Devour 1 (As this enters the battlefield, you may sacrifice any number of creatures. This creature enters the battlefield with twice that many +1/+1 counters on it.) - this.addAbility(new DevourAbility(DevourFactor.Devour1)); + this.addAbility(new DevourAbility(1)); // When Caldera Hellion enters the battlefield, it deals 3 damage to each creature. this.addAbility(new EntersBattlefieldTriggeredAbility(new DamageAllEffect(3, "it", new FilterCreaturePermanent()))); diff --git a/Mage.Sets/src/mage/cards/c/Caprichrome.java b/Mage.Sets/src/mage/cards/c/Caprichrome.java index cd2e0cbd58b..c520ee2b8fc 100644 --- a/Mage.Sets/src/mage/cards/c/Caprichrome.java +++ b/Mage.Sets/src/mage/cards/c/Caprichrome.java @@ -1,7 +1,6 @@ package mage.cards.c; import mage.MageInt; -import mage.abilities.effects.common.DevourEffect; import mage.abilities.keyword.DevourAbility; import mage.abilities.keyword.FlashAbility; import mage.abilities.keyword.VigilanceAbility; @@ -9,6 +8,8 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; +import mage.filter.common.FilterControlledArtifactPermanent; +import mage.filter.common.FilterControlledPermanent; import java.util.UUID; @@ -17,6 +18,8 @@ import java.util.UUID; */ public final class Caprichrome extends CardImpl { + private static final FilterControlledPermanent filter = new FilterControlledArtifactPermanent("artifact"); + public Caprichrome(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{3}{W}"); @@ -31,7 +34,7 @@ public final class Caprichrome extends CardImpl { this.addAbility(VigilanceAbility.getInstance()); // Devour artifact 1 - this.addAbility(new DevourAbility(DevourEffect.DevourFactor.DevourArtifact1)); + this.addAbility(new DevourAbility(1, filter)); } private Caprichrome(final Caprichrome card) { diff --git a/Mage.Sets/src/mage/cards/f/FeasterOfFools.java b/Mage.Sets/src/mage/cards/f/FeasterOfFools.java index a23bc87fde6..2be6a2da6f8 100644 --- a/Mage.Sets/src/mage/cards/f/FeasterOfFools.java +++ b/Mage.Sets/src/mage/cards/f/FeasterOfFools.java @@ -1,7 +1,6 @@ package mage.cards.f; import mage.MageInt; -import mage.abilities.effects.common.DevourEffect; import mage.abilities.keyword.ConvokeAbility; import mage.abilities.keyword.DevourAbility; import mage.abilities.keyword.FlyingAbility; @@ -31,7 +30,7 @@ public final class FeasterOfFools extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // Devour 2 - this.addAbility(new DevourAbility(DevourEffect.DevourFactor.Devour2)); + this.addAbility(new DevourAbility(2)); } private FeasterOfFools(final FeasterOfFools card) { diff --git a/Mage.Sets/src/mage/cards/f/FeastingHobbit.java b/Mage.Sets/src/mage/cards/f/FeastingHobbit.java new file mode 100644 index 00000000000..c909795dfe7 --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/FeastingHobbit.java @@ -0,0 +1,45 @@ +package mage.cards.f; + +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.combat.CantBeBlockedByCreaturesWithLessPowerEffect; +import mage.abilities.keyword.DevourAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.filter.StaticFilters; + +import java.util.UUID; + +/** + * + * @author Susucr + */ +public final class FeastingHobbit extends CardImpl { + + public FeastingHobbit(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}"); + + this.subtype.add(SubType.HALFLING); + this.subtype.add(SubType.CITIZEN); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Devour Food 3 + this.addAbility(new DevourAbility(3, StaticFilters.FILTER_CONTROLLED_FOOD)); + + // Creatures with power less than Feasting Hobbit's power can't block it. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantBeBlockedByCreaturesWithLessPowerEffect())); + } + + private FeastingHobbit(final FeastingHobbit card) { + super(card); + } + + @Override + public FeastingHobbit copy() { + return new FeastingHobbit(this); + } +} diff --git a/Mage.Sets/src/mage/cards/g/GluttonousSlime.java b/Mage.Sets/src/mage/cards/g/GluttonousSlime.java index f599d6ff402..9467127028b 100644 --- a/Mage.Sets/src/mage/cards/g/GluttonousSlime.java +++ b/Mage.Sets/src/mage/cards/g/GluttonousSlime.java @@ -1,9 +1,7 @@ package mage.cards.g; -import java.util.UUID; import mage.MageInt; -import mage.abilities.effects.common.DevourEffect.DevourFactor; import mage.abilities.keyword.DevourAbility; import mage.abilities.keyword.FlashAbility; import mage.cards.CardImpl; @@ -11,6 +9,8 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; +import java.util.UUID; + /** * * @author LevelX2 @@ -28,7 +28,7 @@ public final class GluttonousSlime extends CardImpl { this.addAbility(FlashAbility.getInstance()); // Devour 1 (As this enters the battlefield, you may sacrifice any number of creatures. This creature enters the battlefield with that many +1/+1 counters on it.) - this.addAbility(new DevourAbility(DevourFactor.Devour1)); + this.addAbility(new DevourAbility(1)); } private GluttonousSlime(final GluttonousSlime card) { diff --git a/Mage.Sets/src/mage/cards/g/GorgerWurm.java b/Mage.Sets/src/mage/cards/g/GorgerWurm.java index 505ad07655f..2aea47e4752 100644 --- a/Mage.Sets/src/mage/cards/g/GorgerWurm.java +++ b/Mage.Sets/src/mage/cards/g/GorgerWurm.java @@ -1,15 +1,15 @@ package mage.cards.g; -import java.util.UUID; import mage.MageInt; -import mage.abilities.effects.common.DevourEffect; import mage.abilities.keyword.DevourAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; +import java.util.UUID; + /** * * @author LevelX2 @@ -25,7 +25,7 @@ public final class GorgerWurm extends CardImpl { this.toughness = new MageInt(5); // Devour 1 (As this enters the battlefield, you may sacrifice any number of creatures. This creature enters the battlefield with twice that many +1/+1 counters on it.) - this.addAbility(new DevourAbility(DevourEffect.DevourFactor.Devour1)); + this.addAbility(new DevourAbility(1)); } private GorgerWurm(final GorgerWurm card) { diff --git a/Mage.Sets/src/mage/cards/h/HellkiteHatchling.java b/Mage.Sets/src/mage/cards/h/HellkiteHatchling.java index a840b2155c1..878b14dee8a 100644 --- a/Mage.Sets/src/mage/cards/h/HellkiteHatchling.java +++ b/Mage.Sets/src/mage/cards/h/HellkiteHatchling.java @@ -6,7 +6,6 @@ import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.DevouredCreaturesCondition; import mage.abilities.decorator.ConditionalContinuousEffect; -import mage.abilities.effects.common.DevourEffect.DevourFactor; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; import mage.abilities.keyword.DevourAbility; import mage.abilities.keyword.FlyingAbility; @@ -34,7 +33,7 @@ public final class HellkiteHatchling extends CardImpl { this.toughness = new MageInt(2); // Devour 1 (As this enters the battlefield, you may sacrifice any number of creatures. This creature enters the battlefield with that many +1/+1 counters on it.) - this.addAbility(new DevourAbility(DevourFactor.Devour1)); + this.addAbility(new DevourAbility(1)); // Hellkite Hatchling has flying and trample if it devoured a creature. Ability ability = new SimpleStaticAbility(new ConditionalContinuousEffect( diff --git a/Mage.Sets/src/mage/cards/m/MarrowChomper.java b/Mage.Sets/src/mage/cards/m/MarrowChomper.java index 12144d213f5..3dff87b74ad 100644 --- a/Mage.Sets/src/mage/cards/m/MarrowChomper.java +++ b/Mage.Sets/src/mage/cards/m/MarrowChomper.java @@ -1,11 +1,9 @@ package mage.cards.m; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.dynamicvalue.common.DevouredCreaturesCount; -import mage.abilities.effects.common.DevourEffect; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.keyword.DevourAbility; import mage.cards.CardImpl; @@ -13,6 +11,8 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; +import java.util.UUID; + /** * * @author LevelX2 @@ -30,7 +30,7 @@ public final class MarrowChomper extends CardImpl { this.toughness = new MageInt(3); // Devour 2 (As this enters the battlefield, you may sacrifice any number of creatures. This creature enters the battlefield with twice that many +1/+1 counters on it.) - this.addAbility(new DevourAbility(DevourEffect.DevourFactor.Devour2)); + this.addAbility(new DevourAbility(2)); // When Marrow Chomper enters the battlefield, you gain 2 life for each creature it devoured. this.addAbility(new EntersBattlefieldTriggeredAbility(new GainLifeEffect(new DevouredCreaturesCount(2)))); diff --git a/Mage.Sets/src/mage/cards/m/Mycoloth.java b/Mage.Sets/src/mage/cards/m/Mycoloth.java index 544e16e6eb1..d8b13fc2e15 100644 --- a/Mage.Sets/src/mage/cards/m/Mycoloth.java +++ b/Mage.Sets/src/mage/cards/m/Mycoloth.java @@ -1,12 +1,10 @@ package mage.cards.m; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.common.CreateTokenEffect; -import mage.abilities.effects.common.DevourEffect.DevourFactor; import mage.abilities.keyword.DevourAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -16,6 +14,8 @@ import mage.constants.TargetController; import mage.counters.CounterType; import mage.game.permanent.token.SaprolingToken; +import java.util.UUID; + /** * * @author LevelX2 @@ -30,7 +30,7 @@ public final class Mycoloth extends CardImpl { this.toughness = new MageInt(4); // Devour 2 (As this enters the battlefield, you may sacrifice any number of creatures. This creature enters the battlefield with twice that many +1/+1 counters on it.) - this.addAbility(new DevourAbility(DevourFactor.Devour2)); + this.addAbility(new DevourAbility(2)); // At the beginning of your upkeep, create a 1/1 green Saproling creature token for each +1/+1 counter on Mycoloth. this.addAbility(new BeginningOfUpkeepTriggeredAbility( diff --git a/Mage.Sets/src/mage/cards/p/PredatorDragon.java b/Mage.Sets/src/mage/cards/p/PredatorDragon.java index 7c15471fa0f..630176cbe7c 100644 --- a/Mage.Sets/src/mage/cards/p/PredatorDragon.java +++ b/Mage.Sets/src/mage/cards/p/PredatorDragon.java @@ -1,9 +1,7 @@ package mage.cards.p; -import java.util.UUID; import mage.MageInt; -import mage.abilities.effects.common.DevourEffect.DevourFactor; import mage.abilities.keyword.DevourAbility; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.HasteAbility; @@ -12,6 +10,8 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; +import java.util.UUID; + /** * * @author LevelX2 @@ -30,7 +30,7 @@ public final class PredatorDragon extends CardImpl { this.addAbility(HasteAbility.getInstance()); // Devour 2 (As this enters the battlefield, you may sacrifice any number of creatures. This creature enters the battlefield with twice that many +1/+1 counters on it.) - this.addAbility(new DevourAbility(DevourFactor.Devour2)); + this.addAbility(new DevourAbility(2)); } private PredatorDragon(final PredatorDragon card) { diff --git a/Mage.Sets/src/mage/cards/p/PreyseizerDragon.java b/Mage.Sets/src/mage/cards/p/PreyseizerDragon.java index 6230650cbb6..06227dcff2d 100644 --- a/Mage.Sets/src/mage/cards/p/PreyseizerDragon.java +++ b/Mage.Sets/src/mage/cards/p/PreyseizerDragon.java @@ -1,13 +1,11 @@ package mage.cards.p; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.common.DamageTargetEffect; -import mage.abilities.effects.common.DevourEffect.DevourFactor; import mage.abilities.keyword.DevourAbility; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; @@ -17,6 +15,8 @@ import mage.constants.SubType; import mage.counters.CounterType; import mage.target.common.TargetAnyTarget; +import java.util.UUID; + /** * * @author LevelX2 @@ -34,7 +34,7 @@ public final class PreyseizerDragon extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // Devour 2 (As this enters the battlefield, you may sacrifice any number of creatures. This creature enters the battlefield with twice that many +1/+1 counters on it.) - this.addAbility(new DevourAbility(DevourFactor.Devour2)); + this.addAbility(new DevourAbility(2)); // Whenever Preyseizer Dragon attacks, it deals damage to any target equal to the number of +1/+1 counters on Preyseizer Dragon. Ability ability = new AttacksTriggeredAbility(new DamageTargetEffect(new CountersSourceCount(CounterType.P1P1)), false); diff --git a/Mage.Sets/src/mage/cards/r/RavenousGigantotherium.java b/Mage.Sets/src/mage/cards/r/RavenousGigantotherium.java index e861033b416..1555f8c76ee 100644 --- a/Mage.Sets/src/mage/cards/r/RavenousGigantotherium.java +++ b/Mage.Sets/src/mage/cards/r/RavenousGigantotherium.java @@ -5,7 +5,6 @@ import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DamageMultiEffect; -import mage.abilities.effects.common.DevourEffect; import mage.abilities.keyword.DevourAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -37,7 +36,7 @@ public final class RavenousGigantotherium extends CardImpl { this.toughness = new MageInt(3); // Devour 3 - this.addAbility(new DevourAbility(DevourEffect.DevourFactor.Devour3)); + this.addAbility(new DevourAbility(3)); // When Ravenous Gigantotherium enters the battlefield, it deals X damage divided as you choose among up to X target creatures, where X is its power. Each of those creatures deals damage equal to its power to Ravenous Gigantotherium. this.addAbility(new RavenousGigantotheriumAbility()); diff --git a/Mage.Sets/src/mage/cards/s/Skullmulcher.java b/Mage.Sets/src/mage/cards/s/Skullmulcher.java index 7a2c91b595a..bfa95051b25 100644 --- a/Mage.Sets/src/mage/cards/s/Skullmulcher.java +++ b/Mage.Sets/src/mage/cards/s/Skullmulcher.java @@ -1,11 +1,9 @@ package mage.cards.s; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.dynamicvalue.common.DevouredCreaturesCount; -import mage.abilities.effects.common.DevourEffect.DevourFactor; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.keyword.DevourAbility; import mage.cards.CardImpl; @@ -13,6 +11,8 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; +import java.util.UUID; + /** * * @author LevelX2 @@ -27,7 +27,7 @@ public final class Skullmulcher extends CardImpl { this.toughness = new MageInt(3); // Devour 1 (As this enters the battlefield, you may sacrifice any number of creatures. This creature enters the battlefield with twice that many +1/+1 counters on it.) - this.addAbility(new DevourAbility(DevourFactor.Devour1)); + this.addAbility(new DevourAbility(1)); // When Skullmulcher enters the battlefield, draw a card for each creature it devoured. this.addAbility(new EntersBattlefieldTriggeredAbility( diff --git a/Mage.Sets/src/mage/cards/t/TarFiend.java b/Mage.Sets/src/mage/cards/t/TarFiend.java index 0c73fe7b2c8..8fcecbb2792 100644 --- a/Mage.Sets/src/mage/cards/t/TarFiend.java +++ b/Mage.Sets/src/mage/cards/t/TarFiend.java @@ -1,12 +1,10 @@ package mage.cards.t; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.dynamicvalue.common.DevouredCreaturesCount; -import mage.abilities.effects.common.DevourEffect.DevourFactor; import mage.abilities.effects.common.discard.DiscardTargetEffect; import mage.abilities.keyword.DevourAbility; import mage.cards.CardImpl; @@ -15,6 +13,8 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.target.TargetPlayer; +import java.util.UUID; + /** * * @author LevelX2 @@ -29,7 +29,7 @@ public final class TarFiend extends CardImpl { this.toughness = new MageInt(4); // Devour 2 (As this enters the battlefield, you may sacrifice any number of creatures. This creature enters the battlefield with twice that many +1/+1 counters on it.) - this.addAbility(new DevourAbility(DevourFactor.Devour2)); + this.addAbility(new DevourAbility(2)); // When Tar Fiend enters the battlefield, target player discards a card for each creature it devoured. Ability ability = new EntersBattlefieldTriggeredAbility(new DiscardTargetEffect(new DevouredCreaturesCount())); diff --git a/Mage.Sets/src/mage/cards/t/ThornThrashViashino.java b/Mage.Sets/src/mage/cards/t/ThornThrashViashino.java index 4adcf3c75b0..1c73879ce90 100644 --- a/Mage.Sets/src/mage/cards/t/ThornThrashViashino.java +++ b/Mage.Sets/src/mage/cards/t/ThornThrashViashino.java @@ -1,21 +1,21 @@ package mage.cards.t; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.common.DevourEffect.DevourFactor; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; import mage.abilities.keyword.DevourAbility; import mage.abilities.keyword.TrampleAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Duration; +import mage.constants.SubType; import mage.constants.Zone; +import java.util.UUID; + /** * * @author LevelX2 @@ -31,7 +31,7 @@ public final class ThornThrashViashino extends CardImpl { this.toughness = new MageInt(2); // Devour 2 (As this enters the battlefield, you may sacrifice any number of creatures. This creature enters the battlefield with twice that many +1/+1 counters on it.) - this.addAbility(new DevourAbility(DevourFactor.Devour2)); + this.addAbility(new DevourAbility(2)); // {G}: Thorn-Thrash Viashino gains trample until end of turn. this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new GainAbilitySourceEffect(TrampleAbility.getInstance(), Duration.EndOfTurn),new ManaCostsImpl<>("{G}"))); diff --git a/Mage.Sets/src/mage/cards/t/ThromokTheInsatiable.java b/Mage.Sets/src/mage/cards/t/ThromokTheInsatiable.java index afd5741b557..b7a13b6d3f6 100644 --- a/Mage.Sets/src/mage/cards/t/ThromokTheInsatiable.java +++ b/Mage.Sets/src/mage/cards/t/ThromokTheInsatiable.java @@ -1,9 +1,7 @@ package mage.cards.t; -import java.util.UUID; import mage.MageInt; -import mage.abilities.effects.common.DevourEffect.DevourFactor; import mage.abilities.keyword.DevourAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -11,6 +9,8 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.constants.SuperType; +import java.util.UUID; + /** * * @author LevelX2 @@ -18,7 +18,7 @@ import mage.constants.SuperType; public final class ThromokTheInsatiable extends CardImpl { public ThromokTheInsatiable(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{R}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}{G}"); this.supertype.add(SuperType.LEGENDARY); this.subtype.add(SubType.HELLION); @@ -26,7 +26,7 @@ public final class ThromokTheInsatiable extends CardImpl { this.toughness = new MageInt(0); // Devour X, where X is the number of creatures devoured this way (As this enters the battlefield, you may sacrifice any number of creatures. This creature enters the battlefield with X +1/+1 counters on it for each of those creatures.) - this.addAbility(new DevourAbility(DevourFactor.DevourX)); + this.addAbility(DevourAbility.DevourX()); } private ThromokTheInsatiable(final ThromokTheInsatiable card) { diff --git a/Mage.Sets/src/mage/cards/t/ThunderThrashElder.java b/Mage.Sets/src/mage/cards/t/ThunderThrashElder.java index 48847f9898d..28c86ac1095 100644 --- a/Mage.Sets/src/mage/cards/t/ThunderThrashElder.java +++ b/Mage.Sets/src/mage/cards/t/ThunderThrashElder.java @@ -1,15 +1,15 @@ package mage.cards.t; -import java.util.UUID; import mage.MageInt; -import mage.abilities.effects.common.DevourEffect.DevourFactor; import mage.abilities.keyword.DevourAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; +import java.util.UUID; + /** * * @author LevelX2 @@ -25,7 +25,7 @@ public final class ThunderThrashElder extends CardImpl { this.toughness = new MageInt(1); // Devour 3 (As this enters the battlefield, you may sacrifice any number of creatures. This creature enters the battlefield with twice that many +1/+1 counters on it.) - this.addAbility(new DevourAbility(DevourFactor.Devour3)); + this.addAbility(new DevourAbility(3)); } private ThunderThrashElder(final ThunderThrashElder card) { diff --git a/Mage.Sets/src/mage/cards/v/VoraciousDragon.java b/Mage.Sets/src/mage/cards/v/VoraciousDragon.java index 532ff9139fe..8b5c61f23e7 100644 --- a/Mage.Sets/src/mage/cards/v/VoraciousDragon.java +++ b/Mage.Sets/src/mage/cards/v/VoraciousDragon.java @@ -7,7 +7,6 @@ import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.effects.Effect; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.DevourEffect; -import mage.abilities.effects.common.DevourEffect.DevourFactor; import mage.abilities.keyword.DevourAbility; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; @@ -36,7 +35,7 @@ public final class VoraciousDragon extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // Devour 1 (As this enters the battlefield, you may sacrifice any number of creatures. This creature enters the battlefield with that many +1/+1 counters on it.) - this.addAbility(new DevourAbility(DevourFactor.Devour1)); + this.addAbility(new DevourAbility(1)); // When Voracious Dragon enters the battlefield, it deals damage to any target equal to twice the number of Goblins it devoured. Ability ability = new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(TwiceDevouredGoblins.instance, "it"), false); diff --git a/Mage.Sets/src/mage/sets/TalesOfMiddleEarthCommander.java b/Mage.Sets/src/mage/sets/TalesOfMiddleEarthCommander.java index fb22c1f6d85..85a585ef983 100644 --- a/Mage.Sets/src/mage/sets/TalesOfMiddleEarthCommander.java +++ b/Mage.Sets/src/mage/sets/TalesOfMiddleEarthCommander.java @@ -99,6 +99,7 @@ public final class TalesOfMiddleEarthCommander extends ExpansionSet { cards.add(new SetCardInfo("Farmer Cotton", 55, Rarity.RARE, mage.cards.f.FarmerCotton.class)); cards.add(new SetCardInfo("Farseek", 244, Rarity.COMMON, mage.cards.f.Farseek.class)); cards.add(new SetCardInfo("Fealty to the Realm", 21, Rarity.RARE, mage.cards.f.FealtyToTheRealm.class)); + cards.add(new SetCardInfo("Feasting Hobbit", 37, Rarity.RARE, mage.cards.f.FeastingHobbit.class)); cards.add(new SetCardInfo("Feed the Swarm", 200, Rarity.COMMON, mage.cards.f.FeedTheSwarm.class)); cards.add(new SetCardInfo("Fell the Mighty", 167, Rarity.RARE, mage.cards.f.FellTheMighty.class)); cards.add(new SetCardInfo("Field of Ruin", 308, Rarity.UNCOMMON, mage.cards.f.FieldOfRuin.class)); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/DevourTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/DevourTest.java new file mode 100644 index 00000000000..c2687ac93ed --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/DevourTest.java @@ -0,0 +1,354 @@ + +package org.mage.test.cards.abilities.keywords; + +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.TrampleAbility; +import mage.constants.PhaseStep; +import mage.constants.Zone; +import mage.counters.CounterType; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * 702.82. Devour + *
+ * 702.82a Devour is a static ability. “Devour N” means “As this object enters the battlefield, you may sacrifice any number of creatures. This permanent enters the battlefield with N +1/+1 counters on it for each creature sacrificed this way.” + *
+ * 702.82b Some objects have abilities that refer to the number of creatures the permanent devoured. “It devoured” means “sacrificed as a result of its devour ability as it entered the battlefield.” + *
+ * 702.82c Devour [quality] is a variant of devour. “Devour [quality] N” means “As this object enters the battlefield, you may sacrifice any number of [quality] permanents. This permanent enters the battlefield with N +1/+1 counters on it for each permanent sacrificed this way.”
+ *
+ * @author Susucr
+ */
+public class DevourTest extends CardTestPlayerBase {
+
+ private void expectedPossibleTest(
+ String devourer,
+ String devourTargets,
+ int assertCounter,
+ boolean assertLion,
+ boolean assertMyr,
+ boolean assertGinger,
+ boolean assertRelic
+ ) {
+ setStrictChooseMode(true);
+
+ // Chromatic Orrery
+ // {7}
+ // Legendary Artifact
+ //
+ // You may spend mana as though it were mana of any color.
+ //
+ // {T}: Add {C}{C}{C}{C}{C}.
+ //
+ // {5}, {T}: Draw a card for each color among permanents you control.
+ addCard(Zone.BATTLEFIELD, playerA, "Chromatic Orrery", 1);
+
+ addCard(Zone.HAND, playerA, devourer);
+ addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion"); // Creature
+ addCard(Zone.BATTLEFIELD, playerA, "Alpha Myr"); // Creature Artifact
+ addCard(Zone.BATTLEFIELD, playerA, "Gingerbrute"); // Artifact Creature — Food Golem
+ addCard(Zone.BATTLEFIELD, playerA, "Darksteel Relic"); // Artifact
+
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, devourer);
+ if (devourTargets == "") {
+ setChoice(playerA, false); // no to devour
+ } else {
+ setChoice(playerA, true); // yes to devour
+ addTarget(playerA, devourTargets); // devour targets.
+ }
+
+ setStopAt(1, PhaseStep.BEGIN_COMBAT);
+ execute();
+
+ if (devourer.equals(thromok) && assertCounter == 0) {
+ // Thromok is a 0/0, devouring nothing, it just dies due to SBA.
+ assertGraveyardCount(playerA, devourer, 1);
+ } else {
+ assertCounterCount(playerA, devourer, CounterType.P1P1, assertCounter);
+ }
+
+ assertPermanentCount(playerA, "Silvercoat Lion", assertLion ? 1 : 0);
+ assertGraveyardCount(playerA, "Silvercoat Lion", assertLion ? 0 : 1);
+ assertPermanentCount(playerA, "Alpha Myr", assertMyr ? 1 : 0);
+ assertGraveyardCount(playerA, "Alpha Myr", assertMyr ? 0 : 1);
+ assertPermanentCount(playerA, "Gingerbrute", assertGinger ? 1 : 0);
+ assertGraveyardCount(playerA, "Gingerbrute", assertGinger ? 0 : 1);
+ assertPermanentCount(playerA, "Darksteel Relic", assertRelic ? 1 : 0);
+ assertGraveyardCount(playerA, "Darksteel Relic", assertRelic ? 0 : 1);
+ }
+
+ private void expectedIllegalTest(
+ String devourer,
+ String devourTargets
+ ) {
+ setStrictChooseMode(true);
+
+ // Chromatic Orrery
+ // {7}
+ // Legendary Artifact
+ //
+ // You may spend mana as though it were mana of any color.
+ //
+ // {T}: Add {C}{C}{C}{C}{C}.
+ //
+ // {5}, {T}: Draw a card for each color among permanents you control.
+ addCard(Zone.BATTLEFIELD, playerA, "Chromatic Orrery", 1);
+
+ addCard(Zone.HAND, playerA, devourer);
+ addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion"); // Creature
+ addCard(Zone.BATTLEFIELD, playerA, "Alpha Myr"); // Creature Artifact
+ addCard(Zone.BATTLEFIELD, playerA, "Gingerbrute"); // Artifact Creature — Food Golem
+ addCard(Zone.BATTLEFIELD, playerA, "Darksteel Relic"); // Artifact
+
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, devourer);
+ setChoice(playerA, true); // yes to devour
+ addTarget(playerA, devourTargets); // devour targets.
+
+ boolean legal = true;
+ try {
+ setStopAt(1, PhaseStep.BEGIN_COMBAT);
+ execute();
+ } catch (AssertionError e) {
+ if (e.getMessage().startsWith("PlayerA - Targets list was setup by addTarget with [" + devourTargets + "], but not used")) {
+ legal = false;
+ }
+ } finally {
+ assert !legal;
+ }
+ }
+
+ // Gorger Wurm
+ // {3}{R}{G}
+ // Creature — Wurm
+ //
+ // Devour 1
+ //
+ // 5/5
+ private static final String gorgerWurm = "Gorger Wurm";
+
+ @Test
+ public void Wurm_NoDevour() {
+ expectedPossibleTest(gorgerWurm, "",
+ 1 * 0, true, true, true, true);
+ }
+
+ @Test
+ public void Wurm_OneDevour() {
+ expectedPossibleTest(gorgerWurm, "Alpha Myr",
+ 1 * 1, true, false, true, true);
+ }
+
+ @Test
+ public void Wurm_TwoDevour() {
+ expectedPossibleTest(gorgerWurm, "Alpha Myr^Gingerbrute",
+ 1 * 2, true, false, false, true);
+ }
+
+ @Test
+ public void Wurm_ThreeDevour() {
+ expectedPossibleTest(gorgerWurm, "Alpha Myr^Gingerbrute^Silvercoat Lion",
+ 1 * 3, false, false, false, true);
+ }
+
+ @Test
+ public void Wurm_IllegalDevour() {
+ expectedIllegalTest(gorgerWurm, "Darksteel Relic");
+ }
+
+ // Thromok the Insatiable
+ // {3}{R}{G}
+ // Legendary Creature — Hellion
+ //
+ // Devour X, where X is the number of creatures devoured this way
+ //
+ // 0/0
+ private static final String thromok = "Thromok the Insatiable";
+
+ @Test
+ public void Thromok_NoDevour() {
+ expectedPossibleTest(thromok, "",
+ 0 * 0, true, true, true, true);
+ }
+
+ @Test
+ public void Thromok_OneDevour() {
+ expectedPossibleTest(thromok, "Alpha Myr",
+ 1 * 1, true, false, true, true);
+ }
+
+ @Test
+ public void Thromok_TwoDevour() {
+ expectedPossibleTest(thromok, "Alpha Myr^Gingerbrute",
+ 2 * 2, true, false, false, true);
+ }
+
+ @Test
+ public void Thromok_ThreeDevour() {
+ expectedPossibleTest(thromok, "Alpha Myr^Gingerbrute^Silvercoat Lion",
+ 3 * 3, false, false, false, true);
+ }
+
+ @Test
+ public void Thromok_IllegalDevour() {
+ expectedIllegalTest(thromok, "Darksteel Relic");
+ }
+
+ // Feasting Hobbit
+ // {1}{G}
+ // Creature — Halfling Citizen
+ //
+ // Devour Food 3
+ //
+ // Creatures with power less than Feasting Hobbit’s power can’t block it.
+ private static final String hobbit = "Feasting Hobbit";
+
+ @Test
+ public void Hobbit_NoDevour() {
+ expectedPossibleTest(hobbit, "",
+ 3 * 0, true, true, true, true);
+ }
+
+ @Test
+ public void Hobbit_OneDevour() {
+ expectedPossibleTest(hobbit, "Gingerbrute",
+ 3 * 1, true, true, false, true);
+ }
+
+ @Test
+ public void Hobbit_IllegalDevour() {
+ expectedIllegalTest(hobbit, "Alpha Myr");
+ }
+
+ // Caprichrome
+ // {3}{W}
+ // Artifact Creature — Goat
+ //
+ // Flash
+ //
+ // Vigilance
+ //
+ // Devour artifact 1
+ //
+ // 2/2
+ private static final String caprichrome = "Caprichrome";
+
+ @Test
+ public void Caprichrome_NoDevour() {
+ expectedPossibleTest(caprichrome, "",
+ 1 * 0, true, true, true, true);
+ }
+
+ @Test
+ public void Caprichrome_OneDevour() {
+ expectedPossibleTest(caprichrome, "Alpha Myr",
+ 1 * 1, true, false, true, true);
+ }
+
+ @Test
+ public void Caprichrome_TwoDevour() {
+ expectedPossibleTest(caprichrome, "Alpha Myr^Gingerbrute",
+ 1 * 2, true, false, false, true);
+ }
+
+ @Test
+ public void Caprichrome_ThreeDevour() {
+ expectedPossibleTest(caprichrome, "Alpha Myr^Gingerbrute^Darksteel Relic",
+ 1 * 3, true, false, false, false);
+ }
+
+ @Test
+ public void Caprichrome_IllegalDevour() {
+ expectedIllegalTest(caprichrome, "Silvercoat Lion");
+ }
+
+ // Hellkite Hatchling
+ // {2}{R}{G}
+ // Creature — Dragon
+ //
+ // Devour 1
+ //
+ // Hellkite Hatchling has flying and trample if it devoured a creature.
+ //
+ // 2/2
+ private static final String hatchling = "Hellkite Hatchling";
+
+ @Test
+ public void Hatchling_NoDevour() {
+ expectedPossibleTest(hatchling, "",
+ 1 * 0, true, true, true, true);
+ assertAbility(playerA, hatchling, FlyingAbility.getInstance(), false);
+ assertAbility(playerA, hatchling, TrampleAbility.getInstance(), false);
+ }
+
+ @Test
+ public void Hatchling_OneDevour() {
+ expectedPossibleTest(hatchling, "Alpha Myr",
+ 1 * 1, true, false, true, true);
+ assertAbility(playerA, hatchling, FlyingAbility.getInstance(), true);
+ assertAbility(playerA, hatchling, TrampleAbility.getInstance(), true);
+ }
+
+ @Test
+ public void Hatchling_TwoDevour() {
+ expectedPossibleTest(hatchling, "Alpha Myr^Gingerbrute",
+ 1 * 2, true, false, false, true);
+ assertAbility(playerA, hatchling, FlyingAbility.getInstance(), true);
+ assertAbility(playerA, hatchling, TrampleAbility.getInstance(), true);
+ }
+
+ @Test
+ public void Hatchling_ThreeDevour() {
+ expectedPossibleTest(hatchling, "Alpha Myr^Gingerbrute^Silvercoat Lion",
+ 1 * 3, false, false, false, true);
+ assertAbility(playerA, hatchling, FlyingAbility.getInstance(), true);
+ assertAbility(playerA, hatchling, TrampleAbility.getInstance(), true);
+ }
+
+ @Test
+ public void Hatchling_IllegalDevour() {
+ expectedIllegalTest(hatchling, "Darksteel Relic");
+ }
+
+ // Marrow Chomper
+ // {3}{B}{G}
+ // Creature — Zombie Lizard
+ //
+ // Devour 2
+ //
+ // When Marrow Chomper enters the battlefield, you gain 2 life for each creature it devoured.
+ private static final String chomper = "Marrow Chomper";
+
+ @Test
+ public void Chomper_NoDevour() {
+ expectedPossibleTest(chomper, "",
+ 2 * 0, true, true, true, true);
+ assertLife(playerA, 20 + 2 * 0);
+ }
+
+ @Test
+ public void Chomper_OneDevour() {
+ expectedPossibleTest(chomper, "Alpha Myr",
+ 2 * 1, true, false, true, true);
+ assertLife(playerA, 20 + 2 * 1);
+ }
+
+ @Test
+ public void Chomper_TwoDevour() {
+ expectedPossibleTest(chomper, "Alpha Myr^Gingerbrute",
+ 2 * 2, true, false, false, true);
+ assertLife(playerA, 20 + 2 * 2);
+ }
+
+ @Test
+ public void Chomper_ThreeDevour() {
+ expectedPossibleTest(chomper, "Alpha Myr^Gingerbrute^Silvercoat Lion",
+ 2 * 3, false, false, false, true);
+ assertLife(playerA, 20 + 2 * 3);
+ }
+
+ @Test
+ public void Chomper_IllegalDevour() {
+ expectedIllegalTest(chomper, "Darksteel Relic");
+ }
+}
\ No newline at end of file
diff --git a/Mage/src/main/java/mage/abilities/effects/common/DevourEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DevourEffect.java
index 64be3fed9b6..9940e61d10e 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/DevourEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/DevourEffect.java
@@ -3,11 +3,11 @@ package mage.abilities.effects.common;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.effects.ReplacementEffectImpl;
-import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.counters.CounterType;
import mage.filter.common.FilterControlledPermanent;
+import mage.filter.predicate.Predicate;
import mage.filter.predicate.mageobject.AnotherPredicate;
import mage.game.Game;
import mage.game.events.EntersTheBattlefieldEvent;
@@ -16,6 +16,7 @@ import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.Target;
import mage.target.common.TargetControlledPermanent;
+import mage.util.CardUtil;
import java.util.ArrayList;
import java.util.Collections;
@@ -32,20 +33,30 @@ import java.util.UUID;
* to the number of creatures the permanent devoured. "It devoured" means
* "sacrificed as a result of its devour ability as it entered the battlefield."
*
- * @author LevelX2
+ * @author LevelX2, Susucr
*/
public class DevourEffect extends ReplacementEffectImpl {
- private final DevourFactor devourFactor;
+ // how many counters per devoured permanent.
+ // Integer.MAX_VALUE is a special value that means "X, where X is the number of devoured permanent"
+ private final int devourFactor;
+ // For text generation, the filter's message is expected to be the singular
+ // type word in the devour ability. e.g. "Food" "artifact" "creature".
+ // "creature" is a special case as the rule will not mention it.
+ //
+ // 's' will be added to pluralize, so far so good with the current text generation.
+ private final FilterControlledPermanent filterDevoured;
- public DevourEffect(DevourFactor devourFactor) {
+ public DevourEffect(int devourFactor, FilterControlledPermanent filterDevoured) {
super(Duration.EndOfGame, Outcome.Detriment);
this.devourFactor = devourFactor;
+ this.filterDevoured = filterDevoured;
}
- public DevourEffect(final DevourEffect effect) {
+ private DevourEffect(final DevourEffect effect) {
super(effect);
this.devourFactor = effect.devourFactor;
+ this.filterDevoured = effect.filterDevoured;
}
@Override
@@ -75,12 +86,19 @@ public class DevourEffect extends ReplacementEffectImpl {
if (creature == null || controller == null) {
return false;
}
- Target target = new TargetControlledPermanent(1, Integer.MAX_VALUE, devourFactor.getFilter(), true);
+
+ FilterControlledPermanent filter = new FilterControlledPermanent(filterDevoured.getMessage() + "s to devour");
+ for (Predicate predicate : filterDevoured.getPredicates()) {
+ filter.add(predicate);
+ }
+ filter.add(AnotherPredicate.instance);
+
+ Target target = new TargetControlledPermanent(1, Integer.MAX_VALUE, filter, true);
target.setRequired(false);
if (!target.canChoose(source.getControllerId(), source, game)) {
return false;
}
- if (!controller.chooseUse(Outcome.Detriment, "Devour " + devourFactor.getCardType().toString().toLowerCase() + "s?", source, game)) {
+ if (!controller.chooseUse(Outcome.Detriment, "Devour " + filterDevoured.getMessage() + "s?", source, game)) {
return false;
}
controller.chooseTarget(Outcome.Detriment, target, source, game);
@@ -96,16 +114,19 @@ public class DevourEffect extends ReplacementEffectImpl {
devouredCreatures++;
}
}
- if (!game.isSimulation()) {
- game.informPlayers(creature.getLogName() + " devours " + devouredCreatures + " " + devourFactor.getCardType().toString().toLowerCase() + "s");
- }
+
+ game.informPlayers(creature.getLogName()
+ + " devours " + devouredCreatures + " "
+ + filterDevoured.getMessage() + (devouredCreatures > 1 ? "s" : "")
+ );
+
game.getState().processAction(game); // need for multistep effects
int amountCounters;
- if (devourFactor == DevourFactor.DevourX) {
+ if (devourFactor == Integer.MAX_VALUE) {
amountCounters = devouredCreatures * devouredCreatures;
} else {
- amountCounters = devouredCreatures * devourFactor.getFactor();
+ amountCounters = devouredCreatures * devourFactor;
}
creature.addCounters(CounterType.P1P1.createInstance(amountCounters), source.getControllerId(), source, game);
game.getState().setValue(creature.getId().toString() + "devoured", creaturesDevoured);
@@ -114,13 +135,38 @@ public class DevourEffect extends ReplacementEffectImpl {
@Override
public String getText(Mode mode) {
- StringBuilder sb = new StringBuilder(devourFactor.toString());
- sb.append(" (As this enters the battlefield, you may sacrifice any number of ");
- sb.append(devourFactor.getCardType());
- sb.append("s. This creature enters the battlefield with ");
- sb.append(devourFactor.getRuleText());
- sb.append(")");
- return sb.toString();
+ String text = "Devour ";
+
+ String filterMessage = filterDevoured.getMessage();
+ if (!filterMessage.equals("creature")) {
+ text += filterMessage + " ";
+ }
+
+ if (devourFactor == Integer.MAX_VALUE) {
+ text += "X, where X is the number of " + filterMessage + "s devoured this way";
+ } else {
+ text += devourFactor;
+ }
+
+ text += " (As this enters the battlefield, you may sacrifice any number of "
+ + filterMessage + "s. "
+ + "This creature enters the battlefield with ";
+
+ if (devourFactor == Integer.MAX_VALUE) {
+ text += "X +1/+1 counters on it for each of those creatures";
+ } else {
+ if (devourFactor == 2) {
+ text += "twice ";
+ } else if (devourFactor > 2) {
+ text += CardUtil.numberToText(devourFactor) + " times ";
+ }
+
+ text += "that many +1/+1 counters on it";
+ }
+
+ text += ".)";
+
+ return text;
}
public List