diff --git a/Mage.Sets/src/mage/cards/i/IncreasingAmbition.java b/Mage.Sets/src/mage/cards/i/IncreasingAmbition.java index fd82a208830..eb98a4cffe0 100644 --- a/Mage.Sets/src/mage/cards/i/IncreasingAmbition.java +++ b/Mage.Sets/src/mage/cards/i/IncreasingAmbition.java @@ -1,7 +1,6 @@ package mage.cards.i; -import mage.abilities.Ability; -import mage.abilities.condition.Condition; +import mage.abilities.condition.common.CastFromGraveyardSourceCondition; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.decorator.ConditionalOneShotEffect; import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect; @@ -9,10 +8,7 @@ import mage.abilities.keyword.FlashbackAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Zone; import mage.filter.StaticFilters; -import mage.game.Game; -import mage.game.stack.Spell; import mage.target.common.TargetCardInLibrary; import java.util.UUID; @@ -29,7 +25,7 @@ public final class IncreasingAmbition extends CardImpl { this.getSpellAbility().addEffect(new ConditionalOneShotEffect( new SearchLibraryPutInHandEffect(new TargetCardInLibrary(2, StaticFilters.FILTER_CARD), false), new SearchLibraryPutInHandEffect(new TargetCardInLibrary(), false), - IncreasingAmbitionCondition.instance, "Search your library for a card " + + CastFromGraveyardSourceCondition.instance, "Search your library for a card " + "and put that card into your hand. If this spell was cast from a graveyard, " + "instead search your library for two cards and put those cards into your hand. " + "Then shuffle." @@ -48,13 +44,3 @@ public final class IncreasingAmbition extends CardImpl { return new IncreasingAmbition(this); } } - -enum IncreasingAmbitionCondition implements Condition { - instance; - - @Override - public boolean apply(Game game, Ability source) { - Spell spell = game.getSpell(source.getSourceId()); - return spell != null && spell.getFromZone() == Zone.GRAVEYARD; - } -} diff --git a/Mage.Sets/src/mage/cards/i/IncreasingConfusion.java b/Mage.Sets/src/mage/cards/i/IncreasingConfusion.java index d81b2565299..0b755543b71 100644 --- a/Mage.Sets/src/mage/cards/i/IncreasingConfusion.java +++ b/Mage.Sets/src/mage/cards/i/IncreasingConfusion.java @@ -1,31 +1,36 @@ - package mage.cards.i; -import java.util.UUID; -import mage.abilities.Ability; +import mage.abilities.condition.common.CastFromGraveyardSourceCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.MultipliedValue; +import mage.abilities.dynamicvalue.common.ManacostVariableValue; +import mage.abilities.effects.common.MillCardsTargetEffect; import mage.abilities.keyword.FlashbackAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; -import mage.game.Game; -import mage.game.stack.Spell; -import mage.players.Player; +import mage.constants.CardType; import mage.target.TargetPlayer; +import java.util.UUID; + /** - * * @author BetaSteward */ public final class IncreasingConfusion extends CardImpl { - public IncreasingConfusion(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{X}{U}"); + private static final DynamicValue xValue = new MultipliedValue(ManacostVariableValue.REGULAR, 2); + public IncreasingConfusion(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{U}"); // Target player puts the top X cards of their library into their graveyard. If this spell was cast from a graveyard, that player puts twice that many cards into their graveyard instead. - this.getSpellAbility().addEffect(new IncreasingConfusionEffect()); + this.getSpellAbility().addEffect(new ConditionalOneShotEffect( + new MillCardsTargetEffect(xValue), new MillCardsTargetEffect(ManacostVariableValue.REGULAR), + CastFromGraveyardSourceCondition.instance, "target player mills X cards. " + + "If this spell was cast from a graveyard, that player mills twice that many cards" + )); this.getSpellAbility().addTarget(new TargetPlayer()); // Flashback {X}{U} @@ -41,38 +46,3 @@ public final class IncreasingConfusion extends CardImpl { return new IncreasingConfusion(this); } } - -class IncreasingConfusionEffect extends OneShotEffect { - - IncreasingConfusionEffect() { - super(Outcome.Detriment); - staticText = "Target player mills X cards. If this spell was cast from a graveyard, that player mills twice that many cards"; - } - - private IncreasingConfusionEffect(final IncreasingConfusionEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getFirstTarget()); - if (player != null) { - int amount = source.getManaCostsToPay().getX(); - Spell spell = (Spell) game.getStack().getStackObject(source.getSourceId()); - if (spell != null) { - if (spell.getFromZone() == Zone.GRAVEYARD) { - amount *= 2; - } - player.millCards(amount, source, game); - return true; - } - } - return false; - } - - @Override - public IncreasingConfusionEffect copy() { - return new IncreasingConfusionEffect(this); - } - -} diff --git a/Mage.Sets/src/mage/cards/i/IncreasingDevotion.java b/Mage.Sets/src/mage/cards/i/IncreasingDevotion.java index a84bbf59dbf..1fada50be94 100644 --- a/Mage.Sets/src/mage/cards/i/IncreasingDevotion.java +++ b/Mage.Sets/src/mage/cards/i/IncreasingDevotion.java @@ -1,23 +1,18 @@ - package mage.cards.i; -import java.util.UUID; -import mage.abilities.Ability; +import mage.abilities.condition.common.CastFromGraveyardSourceCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.keyword.FlashbackAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; -import mage.constants.TimingRule; -import mage.constants.Zone; -import mage.game.Game; import mage.game.permanent.token.HumanToken; -import mage.game.stack.Spell; + +import java.util.UUID; /** - * * @author BetaSteward */ public final class IncreasingDevotion extends CardImpl { @@ -26,7 +21,11 @@ public final class IncreasingDevotion extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{W}{W}"); // Create five 1/1 white Human creature tokens. If this spell was cast from a graveyard, create ten of those tokens instead. - this.getSpellAbility().addEffect(new IncreasingDevotionEffect()); + this.getSpellAbility().addEffect(new ConditionalOneShotEffect( + new CreateTokenEffect(new HumanToken(), 10), new CreateTokenEffect(new HumanToken(), 5), + CastFromGraveyardSourceCondition.instance, "create five 1/1 white Human creature tokens. " + + "If this spell was cast from a graveyard, create ten of those tokens instead" + )); // Flashback {7}{W}{W} this.addAbility(new FlashbackAbility(this, new ManaCostsImpl<>("{7}{W}{W}"))); @@ -41,37 +40,3 @@ public final class IncreasingDevotion extends CardImpl { return new IncreasingDevotion(this); } } - -class IncreasingDevotionEffect extends OneShotEffect { - - private static HumanToken token = new HumanToken(); - - public IncreasingDevotionEffect() { - super(Outcome.PutCreatureInPlay); - staticText = "Create five 1/1 white Human creature tokens. If this spell was cast from a graveyard, create ten of those tokens instead"; - } - - private IncreasingDevotionEffect(final IncreasingDevotionEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - int amount = 5; - Spell spell = (Spell) game.getStack().getStackObject(source.getSourceId()); - if (spell != null) { - if (spell.getFromZone() == Zone.GRAVEYARD) { - amount = 10; - } - token.putOntoBattlefield(amount, game, source, source.getControllerId()); - return true; - } - return false; - } - - @Override - public IncreasingDevotionEffect copy() { - return new IncreasingDevotionEffect(this); - } - -} diff --git a/Mage.Sets/src/mage/cards/i/IncreasingSavagery.java b/Mage.Sets/src/mage/cards/i/IncreasingSavagery.java index 7d35d6be67a..13baa8c554e 100644 --- a/Mage.Sets/src/mage/cards/i/IncreasingSavagery.java +++ b/Mage.Sets/src/mage/cards/i/IncreasingSavagery.java @@ -1,32 +1,33 @@ - package mage.cards.i; -import java.util.UUID; -import mage.abilities.Ability; +import mage.abilities.condition.common.CastFromGraveyardSourceCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; import mage.abilities.keyword.FlashbackAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; import mage.counters.CounterType; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.game.stack.Spell; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author BetaSteward */ public final class IncreasingSavagery extends CardImpl { public IncreasingSavagery(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{2}{G}{G}"); - + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{G}{G}"); // Put five +1/+1 counters on target creature. If this spell was cast from a graveyard, put ten +1/+1 counters on that creature instead. - this.getSpellAbility().addEffect(new IncreasingSavageryEffect()); + this.getSpellAbility().addEffect(new ConditionalOneShotEffect( + new AddCountersTargetEffect(CounterType.P1P1.createInstance(10)), + new AddCountersTargetEffect(CounterType.P1P1.createInstance(5)), + CastFromGraveyardSourceCondition.instance, "put five +1/+1 counters on target creature. " + + "If this spell was cast from a graveyard, put ten +1/+1 counters on that creature instead" + )); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); // Flashback {5}{G}{G} @@ -42,38 +43,3 @@ public final class IncreasingSavagery extends CardImpl { return new IncreasingSavagery(this); } } - -class IncreasingSavageryEffect extends OneShotEffect { - - IncreasingSavageryEffect() { - super(Outcome.BoostCreature); - staticText = "Put five +1/+1 counters on target creature. If this spell was cast from a graveyard, put ten +1/+1 counters on that creature instead"; - } - - private IncreasingSavageryEffect(final IncreasingSavageryEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - int amount = 5; - Spell spell = (Spell) game.getStack().getStackObject(source.getSourceId()); - if (spell != null) { - if (spell.getFromZone() == Zone.GRAVEYARD) { - amount = 10; - } - Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); - if (permanent != null) { - permanent.addCounters(CounterType.P1P1.createInstance(amount), source.getControllerId(), source, game); - } - return true; - } - return false; - } - - @Override - public IncreasingSavageryEffect copy() { - return new IncreasingSavageryEffect(this); - } - -} diff --git a/Mage.Sets/src/mage/cards/i/IncreasingVengeance.java b/Mage.Sets/src/mage/cards/i/IncreasingVengeance.java index 5b33dd8191c..5ea9c47cacf 100644 --- a/Mage.Sets/src/mage/cards/i/IncreasingVengeance.java +++ b/Mage.Sets/src/mage/cards/i/IncreasingVengeance.java @@ -1,19 +1,16 @@ - package mage.cards.i; -import mage.abilities.Ability; +import mage.abilities.condition.common.CastFromGraveyardSourceCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.effects.common.CopyTargetStackObjectEffect; import mage.abilities.keyword.FlashbackAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.TargetController; import mage.filter.FilterSpell; -import mage.filter.predicate.Predicates; -import mage.game.Game; -import mage.game.stack.Spell; -import mage.players.Player; -import mage.target.Target; +import mage.filter.common.FilterInstantOrSorcerySpell; import mage.target.TargetSpell; import java.util.UUID; @@ -23,12 +20,9 @@ import java.util.UUID; */ public final class IncreasingVengeance extends CardImpl { - private static final FilterSpell filter = new FilterSpell("instant or sorcery spell"); + private static final FilterSpell filter = new FilterInstantOrSorcerySpell("instant or sorcery spell you control"); static { - filter.add(Predicates.or( - CardType.INSTANT.getPredicate(), - CardType.SORCERY.getPredicate())); filter.add(TargetController.YOU.getControllerPredicate()); } @@ -36,9 +30,13 @@ public final class IncreasingVengeance extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{R}{R}"); // Copy target instant or sorcery spell you control. If this spell was cast from a graveyard, copy that spell twice instead. You may choose new targets for the copies. - this.getSpellAbility().addEffect(new IncreasingVengeanceEffect()); - Target target = new TargetSpell(filter); - this.getSpellAbility().addTarget(target); + this.getSpellAbility().addEffect(new ConditionalOneShotEffect( + new CopyTargetStackObjectEffect(false, false, true, 2, null), + new CopyTargetStackObjectEffect(), CastFromGraveyardSourceCondition.instance, "copy target " + + "instant or sorcery spell you control. If this spell was cast from a graveyard, " + + "copy that spell twice instead. You may choose new targets for the copies" + )); + this.getSpellAbility().addTarget(new TargetSpell(filter)); // Flashback {3}{R}{R} this.addAbility(new FlashbackAbility(this, new ManaCostsImpl<>("{3}{R}{R}"))); @@ -53,40 +51,3 @@ public final class IncreasingVengeance extends CardImpl { return new IncreasingVengeance(this); } } - -class IncreasingVengeanceEffect extends OneShotEffect { - - IncreasingVengeanceEffect() { - super(Outcome.BoostCreature); - staticText = "Copy target instant or sorcery spell you control. If this spell was cast from a graveyard, copy that spell twice instead. You may choose new targets for the copies"; - } - - private IncreasingVengeanceEffect(final IncreasingVengeanceEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller == null) { - return false; - } - Spell spell = game.getStack().getSpell(getTargetPointer().getFirst(game, source)); - if (spell == null) { - return false; - } - Spell sourceSpell = (Spell) game.getSpell(source.getSourceId()); - int copies = 1; - if (sourceSpell != null && sourceSpell.getFromZone() == Zone.GRAVEYARD) { - copies++; - } - spell.createCopyOnStack(game, source, source.getControllerId(), true, copies); - return true; - } - - @Override - public IncreasingVengeanceEffect copy() { - return new IncreasingVengeanceEffect(this); - } - -} diff --git a/Mage.Sets/src/mage/cards/r/RuthlessNegotiation.java b/Mage.Sets/src/mage/cards/r/RuthlessNegotiation.java new file mode 100644 index 00000000000..86644b473a7 --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/RuthlessNegotiation.java @@ -0,0 +1,45 @@ +package mage.cards.r; + +import mage.abilities.condition.common.CastFromGraveyardSourceCondition; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.ExileFromZoneTargetEffect; +import mage.abilities.keyword.FlashbackAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; +import mage.target.common.TargetOpponent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class RuthlessNegotiation extends CardImpl { + + public RuthlessNegotiation(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{B}"); + + // Target opponent exiles a card from their hand. If this spell was cast from a graveyard, draw a card. + this.getSpellAbility().addEffect(new ExileFromZoneTargetEffect(Zone.HAND, false)); + this.getSpellAbility().addEffect(new ConditionalOneShotEffect( + new DrawCardSourceControllerEffect(1), CastFromGraveyardSourceCondition.instance, + "if this spell was cast from a graveyard, draw a card" + )); + this.getSpellAbility().addTarget(new TargetOpponent()); + + // Flashback {4}{B} + this.addAbility(new FlashbackAbility(this, new ManaCostsImpl<>("{4}{B}"))); + } + + private RuthlessNegotiation(final RuthlessNegotiation card) { + super(card); + } + + @Override + public RuthlessNegotiation copy() { + return new RuthlessNegotiation(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SecretsOfTheKey.java b/Mage.Sets/src/mage/cards/s/SecretsOfTheKey.java index 4e0874441e0..c1fc058916c 100644 --- a/Mage.Sets/src/mage/cards/s/SecretsOfTheKey.java +++ b/Mage.Sets/src/mage/cards/s/SecretsOfTheKey.java @@ -1,7 +1,6 @@ package mage.cards.s; -import mage.abilities.Ability; -import mage.abilities.condition.Condition; +import mage.abilities.condition.common.CastFromGraveyardSourceCondition; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.decorator.ConditionalOneShotEffect; import mage.abilities.effects.keyword.InvestigateEffect; @@ -9,10 +8,6 @@ import mage.abilities.keyword.FlashbackAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.TimingRule; -import mage.constants.Zone; -import mage.game.Game; -import mage.game.stack.Spell; import java.util.UUID; @@ -26,7 +21,7 @@ public final class SecretsOfTheKey extends CardImpl { // Investigate. If this spell was cast from a graveyard, investigate twice instead. this.getSpellAbility().addEffect(new ConditionalOneShotEffect( - new InvestigateEffect(2), new InvestigateEffect(), SecretsOfTheKeyCondition.instance, + new InvestigateEffect(2), new InvestigateEffect(), CastFromGraveyardSourceCondition.instance, "Investigate. If this spell was cast from a graveyard, investigate twice instead." )); @@ -43,13 +38,3 @@ public final class SecretsOfTheKey extends CardImpl { return new SecretsOfTheKey(this); } } - -enum SecretsOfTheKeyCondition implements Condition { - instance; - - @Override - public boolean apply(Game game, Ability source) { - Spell spell = game.getSpell(source.getSourceId()); - return spell != null && spell.getFromZone() == Zone.GRAVEYARD; - } -} diff --git a/Mage.Sets/src/mage/sets/Bloomburrow.java b/Mage.Sets/src/mage/sets/Bloomburrow.java index 0fc20886948..465fb6b105a 100644 --- a/Mage.Sets/src/mage/sets/Bloomburrow.java +++ b/Mage.Sets/src/mage/sets/Bloomburrow.java @@ -162,6 +162,7 @@ public final class Bloomburrow extends ExpansionSet { cards.add(new SetCardInfo("Rockface Village", 259, Rarity.UNCOMMON, mage.cards.r.RockfaceVillage.class)); cards.add(new SetCardInfo("Run Away Together", 67, Rarity.COMMON, mage.cards.r.RunAwayTogether.class)); cards.add(new SetCardInfo("Rust-Shield Rampager", 190, Rarity.COMMON, mage.cards.r.RustShieldRampager.class)); + cards.add(new SetCardInfo("Ruthless Negotiation", 108, Rarity.UNCOMMON, mage.cards.r.RuthlessNegotiation.class)); cards.add(new SetCardInfo("Salvation Swan", 28, Rarity.RARE, mage.cards.s.SalvationSwan.class)); cards.add(new SetCardInfo("Savor", 109, Rarity.COMMON, mage.cards.s.Savor.class)); cards.add(new SetCardInfo("Scales of Shale", 110, Rarity.COMMON, mage.cards.s.ScalesOfShale.class)); diff --git a/Mage/src/main/java/mage/abilities/condition/common/CastFromGraveyardSourceCondition.java b/Mage/src/main/java/mage/abilities/condition/common/CastFromGraveyardSourceCondition.java new file mode 100644 index 00000000000..fed5f041638 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/condition/common/CastFromGraveyardSourceCondition.java @@ -0,0 +1,32 @@ +package mage.abilities.condition.common; + +import mage.abilities.Ability; +import mage.abilities.condition.Condition; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.stack.Spell; + +import java.util.Optional; + +/** + * @author TheElk801 + */ +public enum CastFromGraveyardSourceCondition implements Condition { + instance; + + @Override + public boolean apply(Game game, Ability source) { + return Optional + .ofNullable(source) + .map(Ability::getSourceId) + .map(game::getSpell) + .map(Spell::getFromZone) + .map(Zone.GRAVEYARD::match) + .orElse(false); + } + + @Override + public String toString() { + return "this spell was cast from a graveyard"; + } +}