diff --git a/Mage.Sets/src/mage/cards/r/RottenmouthViper.java b/Mage.Sets/src/mage/cards/r/RottenmouthViper.java new file mode 100644 index 00000000000..ed48843fc16 --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/RottenmouthViper.java @@ -0,0 +1,164 @@ +package mage.cards.r; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.SpellAbility; +import mage.abilities.common.EntersBattlefieldOrAttacksSourceTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.Cost; +import mage.abilities.costs.common.SacrificeXTargetCost; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.CountersSourceCount; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.cost.CostModificationEffectImpl; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.constants.*; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.counters.CounterType; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.Target; +import mage.target.TargetPermanent; +import mage.util.CardUtil; + +/** + * + * @author Momo2907 + */ +public final class RottenmouthViper extends CardImpl { + + public RottenmouthViper(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{B}"); + + this.subtype.add(SubType.ELEMENTAL); + this.subtype.add(SubType.SNAKE); + this.power = new MageInt(6); + this.toughness = new MageInt(6); + + // As an additional cost to cast this spell, you may sacrifice any number of nonland permanents. This spell costs {1} less to cast for each permanent sacrificed this way. + Cost cost = new SacrificeXTargetCost(StaticFilters.FILTER_CONTROLLED_PERMANENT_NON_LAND, true); + cost.setText("you may sacrifice any number of nonland permanents. " + + "This spell costs {1} less to cast for each permanent sacrificed this way"); + this.getSpellAbility().addCost(cost); + this.addAbility(new SimpleStaticAbility(Zone.ALL, new RottenmouthViperCostReductionEffect())); + + // Whenever Rottenmouth Viper enters or attacks, put a blight counter on it. Then for each blight counter on it, each opponent loses 4 life unless that player sacrifices a nonland permanent or discards a card. + Ability ability = new EntersBattlefieldOrAttacksSourceTriggeredAbility( + new AddCountersSourceEffect(CounterType.BLIGHT.createInstance()) + ); + ability.addEffect(new RottenmouthViperEffect(new CountersSourceCount(CounterType.BLIGHT))); + this.addAbility(ability); + } + + private RottenmouthViper(final RottenmouthViper card) { + super(card); + } + + @Override + public RottenmouthViper copy() { + return new RottenmouthViper(this); + } +} + +class RottenmouthViperEffect extends OneShotEffect{ + + DynamicValue blightCounterAmount; + + RottenmouthViperEffect(DynamicValue blightCounterAmount) { + super(Outcome.LoseLife); + this.blightCounterAmount = blightCounterAmount; + this.staticText = "Then for each blight counter on it, each opponent loses 4 life unless that player sacrifices a nonland permanent or discards a card."; + } + + private RottenmouthViperEffect(final RottenmouthViperEffect effect) { + super(effect); + this.blightCounterAmount = effect.blightCounterAmount.copy(); + } + + @Override + public RottenmouthViperEffect copy() { + return new RottenmouthViperEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null){ + int repeat = blightCounterAmount.calculate(game, source, this); + for (int i = 1; i <= repeat; i++) { + + for (UUID opponentId : game.getOpponents(source.getControllerId())) { + Player opponent = game.getPlayer(opponentId); + if (opponent != null) { + int permanents = game.getBattlefield().countAll(StaticFilters.FILTER_PERMANENT_NON_LAND, opponentId, game); + if (permanents > 0 && opponent.chooseUse(outcome, "Sacrifices a nonland permanent? (Iteration " + i + " of " + repeat + ")", + "Otherwise you have to discard a card or lose 4 life.", "Sacrifice", "Discard or life loss", source, game)) { + Target target = new TargetPermanent(StaticFilters.FILTER_CONTROLLED_PERMANENT_NON_LAND); + target.withNotTarget(true); + if (opponent.choose(outcome, target, source, game)) { + Permanent permanent = game.getPermanent(target.getFirstTarget()); + if (permanent != null) { + if (permanent.sacrifice(source, game)) { + continue; + } + } + } + } + if (!opponent.getHand().isEmpty() && opponent.chooseUse(outcome, "Discard a card? (Iteration " + i + " of " + repeat + ")", + "Otherwise you lose 4 life.", "Discard", "Lose 4 life", source, game)) { + opponent.discardOne(false, false, source, game); + continue; + } + opponent.loseLife(4, game, source, false); + } + } + } + return true; + } + return false; + } +} + +class RottenmouthViperCostReductionEffect extends CostModificationEffectImpl{ + + RottenmouthViperCostReductionEffect(){ + super(Duration.WhileOnStack, Outcome.Benefit, CostModificationType.REDUCE_COST); + } + + private RottenmouthViperCostReductionEffect(final RottenmouthViperCostReductionEffect effect) { + super(effect); + } + + @Override + public RottenmouthViperCostReductionEffect copy() { + return new RottenmouthViperCostReductionEffect(this); + } + + @Override + public boolean apply(Game game, Ability source, Ability abilityToModify) { + SpellAbility spellAbility = (SpellAbility) abilityToModify; + int reduction = 0; + for (Cost cost: spellAbility.getCosts()) { + if(!(cost instanceof SacrificeXTargetCost)){ + continue; + } + if (game.inCheckPlayableState()) { + reduction += ((SacrificeXTargetCost) cost).getMaxValue(spellAbility, game); + } else{ + reduction += ((SacrificeXTargetCost) cost).getAmount(); + } + break; + } + CardUtil.adjustCost(spellAbility, reduction); + return true; + } + + @Override + public boolean applies(Ability abilityToModify, Ability source, Game game) { + return abilityToModify instanceof SpellAbility && abilityToModify.getSourceId().equals(source.getSourceId()); + } +} diff --git a/Mage.Sets/src/mage/sets/Bloomburrow.java b/Mage.Sets/src/mage/sets/Bloomburrow.java index 392fa474b9c..9ecfd1102cb 100644 --- a/Mage.Sets/src/mage/sets/Bloomburrow.java +++ b/Mage.Sets/src/mage/sets/Bloomburrow.java @@ -194,6 +194,7 @@ public final class Bloomburrow extends ExpansionSet { cards.add(new SetCardInfo("Repel Calamity", 27, Rarity.UNCOMMON, mage.cards.r.RepelCalamity.class)); cards.add(new SetCardInfo("Reptilian Recruiter", 149, Rarity.UNCOMMON, mage.cards.r.ReptilianRecruiter.class)); cards.add(new SetCardInfo("Rockface Village", 259, Rarity.UNCOMMON, mage.cards.r.RockfaceVillage.class)); + cards.add(new SetCardInfo("Rottenmouth Viper", 107, Rarity.MYTHIC, mage.cards.r.RottenmouthViper.class)); cards.add(new SetCardInfo("Roughshod Duo", 150, Rarity.COMMON, mage.cards.r.RoughshodDuo.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)); diff --git a/Mage/src/main/java/mage/counters/CounterType.java b/Mage/src/main/java/mage/counters/CounterType.java index 722408f84e1..dde98c4a70a 100644 --- a/Mage/src/main/java/mage/counters/CounterType.java +++ b/Mage/src/main/java/mage/counters/CounterType.java @@ -24,6 +24,7 @@ public enum CounterType { AWAKENING("awakening"), BLAZE("blaze"), BLESSING("blessing"), + BLIGHT("blight"), BLOOD("blood"), BLOODLINE("bloodline"), BLOODSTAIN("bloodstain"),