diff --git a/Mage.Sets/src/mage/cards/a/AgentOfMasks.java b/Mage.Sets/src/mage/cards/a/AgentOfMasks.java index eb286459703..000495418b9 100644 --- a/Mage.Sets/src/mage/cards/a/AgentOfMasks.java +++ b/Mage.Sets/src/mage/cards/a/AgentOfMasks.java @@ -1,16 +1,13 @@ package mage.cards.a; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.LoseLifeOpponentsYouGainLifeLostEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; import mage.constants.SubType; import mage.constants.TargetController; -import mage.game.Game; import java.util.UUID; @@ -27,7 +24,7 @@ public final class AgentOfMasks extends CardImpl { // At the beginning of your upkeep, each opponent loses 1 life. You gain life equal to the life lost this way. this.power = new MageInt(2); this.toughness = new MageInt(3); - this.addAbility(new BeginningOfUpkeepTriggeredAbility(new AgentOfMasksEffect(), TargetController.YOU, false)); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new LoseLifeOpponentsYouGainLifeLostEffect(1), TargetController.YOU, false)); } private AgentOfMasks(final AgentOfMasks card) { @@ -39,31 +36,3 @@ public final class AgentOfMasks extends CardImpl { return new AgentOfMasks(this); } } - -class AgentOfMasksEffect extends OneShotEffect { - public AgentOfMasksEffect() { - super(Outcome.Damage); - staticText = "each opponent loses 1 life. You gain life equal to the life lost this way"; - } - - private AgentOfMasksEffect(final AgentOfMasksEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - int loseLife = 0; - for (UUID opponentId : game.getOpponents(source.getControllerId())) { - loseLife += game.getPlayer(opponentId).loseLife(1, game, source, false); - } - if (loseLife > 0) - game.getPlayer(source.getControllerId()).gainLife(loseLife, game, source); - return true; - } - - @Override - public AgentOfMasksEffect copy() { - return new AgentOfMasksEffect(this); - } - -} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/b/BloodTithe.java b/Mage.Sets/src/mage/cards/b/BloodTithe.java index 295e489dd14..a8af357cacd 100644 --- a/Mage.Sets/src/mage/cards/b/BloodTithe.java +++ b/Mage.Sets/src/mage/cards/b/BloodTithe.java @@ -1,15 +1,11 @@ - - package mage.cards.b; -import java.util.UUID; -import mage.abilities.Ability; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.LoseLifeOpponentsYouGainLifeLostEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; -import mage.game.Game; + +import java.util.UUID; /** * @@ -20,7 +16,8 @@ public final class BloodTithe extends CardImpl { public BloodTithe(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{3}{B}"); - this.getSpellAbility().addEffect(new BloodTitheEffect()); + // Each opponent loses 3 life. You gain life equal to the life lost this way. + this.getSpellAbility().addEffect(new LoseLifeOpponentsYouGainLifeLostEffect(3)); } private BloodTithe(final BloodTithe card) { @@ -33,31 +30,3 @@ public final class BloodTithe extends CardImpl { } } - -class BloodTitheEffect extends OneShotEffect { - - BloodTitheEffect() { - super(Outcome.GainLife); - staticText = "Each opponent loses 3 life. You gain life equal to the life lost this way"; - } - - private BloodTitheEffect(final BloodTitheEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - int lifeLost = 0; - for (UUID opponentId: game.getOpponents(source.getControllerId())) { - lifeLost += game.getPlayer(opponentId).loseLife(3, game, source, false); - } - game.getPlayer(source.getControllerId()).gainLife(lifeLost, game, source); - return true; - } - - @Override - public BloodTitheEffect copy() { - return new BloodTitheEffect(this); - } - -} diff --git a/Mage.Sets/src/mage/cards/b/BubblingCauldron.java b/Mage.Sets/src/mage/cards/b/BubblingCauldron.java index f1e95bd9159..1bf702dfa1d 100644 --- a/Mage.Sets/src/mage/cards/b/BubblingCauldron.java +++ b/Mage.Sets/src/mage/cards/b/BubblingCauldron.java @@ -1,24 +1,21 @@ package mage.cards.b; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.SacrificeTargetCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.effects.common.LoseLifeOpponentsYouGainLifeLostEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; import mage.constants.Zone; import mage.filter.StaticFilters; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.mageobject.NamePredicate; -import mage.game.Game; -import mage.players.Player; -import mage.target.common.TargetControlledCreaturePermanent; + +import java.util.UUID; /** * @@ -41,7 +38,7 @@ public final class BubblingCauldron extends CardImpl { ability1.addCost(new SacrificeTargetCost(StaticFilters.FILTER_CONTROLLED_CREATURE_SHORT_TEXT)); this.addAbility(ability1); // {1}, {T}, Sacrifice a creature named Festering Newt: Each opponent loses 4 life. You gain life equal to the life lost this way. - Ability ability2 = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BubblingCauldronEffect(), new ManaCostsImpl<>("{1}")); + Ability ability2 = new SimpleActivatedAbility(Zone.BATTLEFIELD, new LoseLifeOpponentsYouGainLifeLostEffect(4), new ManaCostsImpl<>("{1}")); ability2.addCost(new TapSourceCost()); ability2.addCost(new SacrificeTargetCost(filter)); this.addAbility(ability2); @@ -56,37 +53,3 @@ public final class BubblingCauldron extends CardImpl { return new BubblingCauldron(this); } } - -class BubblingCauldronEffect extends OneShotEffect { - - BubblingCauldronEffect() { - super(Outcome.GainLife); - staticText = "Each opponent loses 4 life. You gain life equal to the life lost this way"; - } - - private BubblingCauldronEffect(final BubblingCauldronEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - int lostLife = 0; - Player controller = game.getPlayer(source.getControllerId()); - for (UUID opponentId : game.getOpponents(source.getControllerId())) { - Player opponent = game.getPlayer(opponentId); - if (opponent != null) { - lostLife += opponent.loseLife(4, game, source, false); - } - } - if (controller != null) { - controller.gainLife(lostLife, game, source); - } - return true; - } - - @Override - public BubblingCauldronEffect copy() { - return new BubblingCauldronEffect(this); - } - -} diff --git a/Mage.Sets/src/mage/cards/c/ChancellorOfTheDross.java b/Mage.Sets/src/mage/cards/c/ChancellorOfTheDross.java index aab6f6c6b2d..23e846eb7cf 100644 --- a/Mage.Sets/src/mage/cards/c/ChancellorOfTheDross.java +++ b/Mage.Sets/src/mage/cards/c/ChancellorOfTheDross.java @@ -1,22 +1,19 @@ - package mage.cards.c; -import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.DelayedTriggeredAbility; import mage.abilities.common.ChancellorAbility; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.LoseLifeOpponentsYouGainLifeLostEffect; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.LifelinkAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Outcome; import mage.game.Game; import mage.game.events.GameEvent; -import mage.game.events.GameEvent.EventType; + +import java.util.UUID; /** * @@ -24,7 +21,7 @@ import mage.game.events.GameEvent.EventType; */ public final class ChancellorOfTheDross extends CardImpl { - private static String abilityText = "at the beginning of the first upkeep, each opponent loses 3 life, then you gain life equal to the life lost this way"; + private static final String abilityText = "at the beginning of the first upkeep, each opponent loses 3 life, then you gain life equal to the life lost this way"; public ChancellorOfTheDross(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{B}{B}{B}"); @@ -54,7 +51,7 @@ public final class ChancellorOfTheDross extends CardImpl { class ChancellorOfTheDrossDelayedTriggeredAbility extends DelayedTriggeredAbility { ChancellorOfTheDrossDelayedTriggeredAbility () { - super(new ChancellorOfTheDrossEffect()); + super(new LoseLifeOpponentsYouGainLifeLostEffect(3)); } private ChancellorOfTheDrossDelayedTriggeredAbility(final ChancellorOfTheDrossDelayedTriggeredAbility ability) { @@ -75,33 +72,3 @@ class ChancellorOfTheDrossDelayedTriggeredAbility extends DelayedTriggeredAbilit return new ChancellorOfTheDrossDelayedTriggeredAbility(this); } } - -class ChancellorOfTheDrossEffect extends OneShotEffect { - - ChancellorOfTheDrossEffect () { - super(Outcome.Benefit); - staticText = "each opponent loses 3 life, then you gain life equal to the life lost this way"; - } - - private ChancellorOfTheDrossEffect(final ChancellorOfTheDrossEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - int loseLife = 0; - for (UUID opponentId : game.getOpponents(source.getControllerId())) { - loseLife += game.getPlayer(opponentId).loseLife(3, game, source, false); - } - if (loseLife > 0) { - game.getPlayer(source.getControllerId()).gainLife(loseLife, game, source); - } - return true; - } - - @Override - public ChancellorOfTheDrossEffect copy() { - return new ChancellorOfTheDrossEffect(this); - } - -} diff --git a/Mage.Sets/src/mage/cards/d/DebtToTheDeathless.java b/Mage.Sets/src/mage/cards/d/DebtToTheDeathless.java index 4f19ebdc5ee..36766c84201 100644 --- a/Mage.Sets/src/mage/cards/d/DebtToTheDeathless.java +++ b/Mage.Sets/src/mage/cards/d/DebtToTheDeathless.java @@ -1,15 +1,14 @@ - package mage.cards.d; -import java.util.UUID; -import mage.abilities.Ability; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.MultipliedValue; +import mage.abilities.dynamicvalue.common.ManacostVariableValue; +import mage.abilities.effects.common.LoseLifeOpponentsYouGainLifeLostEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; -import mage.game.Game; -import mage.players.Player; + +import java.util.UUID; /** * @@ -17,11 +16,13 @@ import mage.players.Player; */ public final class DebtToTheDeathless extends CardImpl { + private static final DynamicValue xValue = new MultipliedValue(ManacostVariableValue.REGULAR, 2); + public DebtToTheDeathless(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{W}{W}{B}{B}"); // Each opponent loses two times X life. You gain life equal to the life lost this way. - this.getSpellAbility().addEffect(new DebtToTheDeathlessEffect()); + this.getSpellAbility().addEffect(new LoseLifeOpponentsYouGainLifeLostEffect(xValue, "two times X life")); } private DebtToTheDeathless(final DebtToTheDeathless card) { @@ -33,38 +34,3 @@ public final class DebtToTheDeathless extends CardImpl { return new DebtToTheDeathless(this); } } - -class DebtToTheDeathlessEffect extends OneShotEffect { - - DebtToTheDeathlessEffect() { - super(Outcome.Benefit); - this.staticText = "Each opponent loses two times X life. You gain life equal to the life lost this way"; - } - - private DebtToTheDeathlessEffect(final DebtToTheDeathlessEffect effect) { - super(effect); - } - - @Override - public DebtToTheDeathlessEffect copy() { - return new DebtToTheDeathlessEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - int lifeLost = 0; - int xValue = source.getManaCostsToPay().getX(); - for (UUID opponentId : game.getOpponents(source.getControllerId())) { - Player opponent = game.getPlayer(opponentId); - if (opponent != null) { - lifeLost += opponent.loseLife(xValue * 2, game, source, false); - } - } - controller.gainLife(lifeLost, game, source); - return true; - } - return false; - } -} diff --git a/Mage.Sets/src/mage/cards/e/Exsanguinate.java b/Mage.Sets/src/mage/cards/e/Exsanguinate.java index 309e9f7c025..e0bb79d517b 100644 --- a/Mage.Sets/src/mage/cards/e/Exsanguinate.java +++ b/Mage.Sets/src/mage/cards/e/Exsanguinate.java @@ -1,13 +1,12 @@ package mage.cards.e; -import java.util.UUID; -import mage.abilities.Ability; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.dynamicvalue.common.ManacostVariableValue; +import mage.abilities.effects.common.LoseLifeOpponentsYouGainLifeLostEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; -import mage.game.Game; + +import java.util.UUID; /** * @@ -18,7 +17,8 @@ public final class Exsanguinate extends CardImpl { public Exsanguinate(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{B}{B}"); - this.getSpellAbility().addEffect(new ExsanguinateEffect()); + // Each opponent loses X life. You gain life equal to the life lost this way. + this.getSpellAbility().addEffect(new LoseLifeOpponentsYouGainLifeLostEffect(ManacostVariableValue.REGULAR, "X life")); } private Exsanguinate(final Exsanguinate card) { @@ -31,34 +31,3 @@ public final class Exsanguinate extends CardImpl { } } - -class ExsanguinateEffect extends OneShotEffect { - - ExsanguinateEffect() { - super(Outcome.GainLife); - staticText = "Each opponent loses X life. You gain life equal to the life lost this way"; - } - - private ExsanguinateEffect(final ExsanguinateEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - int totalLostLife = 0; - int loseLife = source.getManaCostsToPay().getX(); - for (UUID opponentId : game.getOpponents(source.getControllerId())) { - totalLostLife += game.getPlayer(opponentId).loseLife(loseLife, game, source, false); - } - if (totalLostLife > 0) { - game.getPlayer(source.getControllerId()).gainLife(totalLostLife, game, source); - } - return true; - } - - @Override - public ExsanguinateEffect copy() { - return new ExsanguinateEffect(this); - } - -} diff --git a/Mage.Sets/src/mage/cards/g/GontisMachinations.java b/Mage.Sets/src/mage/cards/g/GontisMachinations.java index 4b8ffd92fd4..c561745b9e1 100644 --- a/Mage.Sets/src/mage/cards/g/GontisMachinations.java +++ b/Mage.Sets/src/mage/cards/g/GontisMachinations.java @@ -1,26 +1,25 @@ package mage.cards.g; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.PayEnergyCost; import mage.abilities.costs.common.SacrificeSourceCost; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.LoseLifeOpponentsYouGainLifeLostEffect; import mage.abilities.effects.common.counter.GetEnergyCountersControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; import mage.constants.WatcherScope; import mage.constants.Zone; import mage.game.Game; import mage.game.events.GameEvent; -import mage.players.Player; import mage.watchers.Watcher; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + /** * @author LevelX2 */ @@ -36,7 +35,7 @@ public final class GontisMachinations extends CardImpl { // Pay {E}{E}, Sacrifice Gonti's Machinations: Each opponent loses 3 life. You gain life equal to the life lost this way. Ability ability = new SimpleActivatedAbility( Zone.BATTLEFIELD, - new GontisMachinationsEffect(), + new LoseLifeOpponentsYouGainLifeLostEffect(3), new PayEnergyCost(2)); ability.addCost(new SacrificeSourceCost()); this.addAbility(ability); @@ -117,38 +116,3 @@ class GontisMachinationsFirstLostLifeThisTurnWatcher extends Watcher { return playersLostLife.getOrDefault(playerId, 0); } } - -class GontisMachinationsEffect extends OneShotEffect { - - GontisMachinationsEffect() { - super(Outcome.GainLife); - staticText = "Each opponent loses 3 life. You gain life equal to the life lost this way"; - } - - private GontisMachinationsEffect(final GontisMachinationsEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - int totalLostLife = 0; - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - for (UUID opponentId : game.getOpponents(source.getControllerId())) { - Player opponent = game.getPlayer(opponentId); - if (opponent != null) { - totalLostLife += game.getPlayer(opponentId).loseLife(3, game, source, false); - } - } - game.getPlayer(source.getControllerId()).gainLife(totalLostLife, game, source); - return true; - } - return false; - } - - @Override - public GontisMachinationsEffect copy() { - return new GontisMachinationsEffect(this); - } - -} diff --git a/Mage.Sets/src/mage/cards/g/GrayMerchantOfAsphodel.java b/Mage.Sets/src/mage/cards/g/GrayMerchantOfAsphodel.java index 8a273da0f28..af2b9d9b315 100644 --- a/Mage.Sets/src/mage/cards/g/GrayMerchantOfAsphodel.java +++ b/Mage.Sets/src/mage/cards/g/GrayMerchantOfAsphodel.java @@ -1,19 +1,14 @@ package mage.cards.g; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.dynamicvalue.common.DevotionCount; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.LoseLifeOpponentsYouGainLifeLostEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; import mage.constants.SubType; -import mage.game.Game; -import mage.players.Player; -import java.util.Objects; import java.util.UUID; /** @@ -29,8 +24,8 @@ public final class GrayMerchantOfAsphodel extends CardImpl { this.toughness = new MageInt(4); // When Gray Merchant of Asphodel enters the battlefield, each opponent loses X life, where X is your devotion to black. You gain life equal to the life lost this way. - this.addAbility(new EntersBattlefieldTriggeredAbility( - new GrayMerchantOfAsphodelEffect(), false + this.addAbility(new EntersBattlefieldTriggeredAbility(new LoseLifeOpponentsYouGainLifeLostEffect( + DevotionCount.B, "X life, where X is your devotion to black"), false ).addHint(DevotionCount.B.getHint())); } @@ -43,42 +38,3 @@ public final class GrayMerchantOfAsphodel extends CardImpl { return new GrayMerchantOfAsphodel(this); } } - -class GrayMerchantOfAsphodelEffect extends OneShotEffect { - - GrayMerchantOfAsphodelEffect() { - super(Outcome.GainLife); - this.staticText = "each opponent loses X life, where X is your devotion to black. " - + "You gain life equal to the life lost this way. " - + DevotionCount.B.getReminder(); - } - - private GrayMerchantOfAsphodelEffect(final GrayMerchantOfAsphodelEffect effect) { - super(effect); - } - - @Override - public GrayMerchantOfAsphodelEffect copy() { - return new GrayMerchantOfAsphodelEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller == null) { - return false; - } - int lifeLost = DevotionCount.B.calculate(game, source, this); - if (lifeLost == 0) { - return true; - } - int totalLifeLost = game - .getOpponents(source.getControllerId()) - .stream() - .map(game::getPlayer) - .filter(Objects::nonNull) - .mapToInt(opponent -> opponent.loseLife(lifeLost, game, source, false)) - .sum(); - return controller.gainLife(totalLifeLost, game, source) > 0; - } -} diff --git a/Mage.Sets/src/mage/cards/k/KokushoTheEveningStar.java b/Mage.Sets/src/mage/cards/k/KokushoTheEveningStar.java index 140d8f05559..8ca0100e461 100644 --- a/Mage.Sets/src/mage/cards/k/KokushoTheEveningStar.java +++ b/Mage.Sets/src/mage/cards/k/KokushoTheEveningStar.java @@ -1,20 +1,16 @@ - - package mage.cards.k; -import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.DiesSourceTriggeredAbility; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.LoseLifeOpponentsYouGainLifeLostEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Outcome; import mage.constants.SuperType; -import mage.game.Game; + +import java.util.UUID; /** * @author Loki @@ -30,7 +26,7 @@ public final class KokushoTheEveningStar extends CardImpl { this.power = new MageInt(5); this.toughness = new MageInt(5); this.addAbility(FlyingAbility.getInstance()); - this.addAbility(new DiesSourceTriggeredAbility(new KokushoTheEveningStarEffect(), false)); + this.addAbility(new DiesSourceTriggeredAbility(new LoseLifeOpponentsYouGainLifeLostEffect(5), false)); } private KokushoTheEveningStar(final KokushoTheEveningStar card) { @@ -43,31 +39,3 @@ public final class KokushoTheEveningStar extends CardImpl { } } - -class KokushoTheEveningStarEffect extends OneShotEffect { - public KokushoTheEveningStarEffect() { - super(Outcome.Damage); - staticText = "each opponent loses 5 life. You gain life equal to the life lost this way"; - } - - private KokushoTheEveningStarEffect(final KokushoTheEveningStarEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - int loseLife = 0; - for (UUID opponentId : game.getOpponents(source.getControllerId())) { - loseLife += game.getPlayer(opponentId).loseLife(5, game, source, false); - } - if (loseLife > 0) - game.getPlayer(source.getControllerId()).gainLife(loseLife, game, source); - return true; - } - - @Override - public KokushoTheEveningStarEffect copy() { - return new KokushoTheEveningStarEffect(this); - } - -} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/m/MalakirBloodwitch.java b/Mage.Sets/src/mage/cards/m/MalakirBloodwitch.java index e817a1bc87f..a822a64684e 100644 --- a/Mage.Sets/src/mage/cards/m/MalakirBloodwitch.java +++ b/Mage.Sets/src/mage/cards/m/MalakirBloodwitch.java @@ -1,24 +1,22 @@ package mage.cards.m; -import java.util.Set; -import java.util.UUID; import mage.MageInt; import mage.ObjectColor; -import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.LoseLifeOpponentsYouGainLifeLostEffect; +import mage.abilities.hint.Hint; import mage.abilities.hint.ValueHint; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.ProtectionAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; import mage.constants.SubType; import mage.filter.common.FilterControlledPermanent; -import mage.game.Game; -import mage.players.Player; + +import java.util.UUID; /** * @@ -26,6 +24,9 @@ import mage.players.Player; */ public final class MalakirBloodwitch extends CardImpl { + private static final DynamicValue xValue = new PermanentsOnBattlefieldCount(new FilterControlledPermanent(SubType.VAMPIRE)); + private static final Hint hint = new ValueHint("Vampires you control", xValue); + public MalakirBloodwitch(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{B}{B}"); this.subtype.add(SubType.VAMPIRE); @@ -41,8 +42,10 @@ public final class MalakirBloodwitch extends CardImpl { this.addAbility(ProtectionAbility.from(ObjectColor.WHITE)); // When Malakir Bloodwitch enters the battlefield, each opponent loses life equal to the number of Vampires you control. You gain life equal to the life lost this way. - this.addAbility(new EntersBattlefieldTriggeredAbility(new MalakirBloodwitchEffect(), false) - .addHint(new ValueHint("Vampires you control", new PermanentsOnBattlefieldCount(new FilterControlledPermanent(SubType.VAMPIRE)))) + this.addAbility(new EntersBattlefieldTriggeredAbility( + new LoseLifeOpponentsYouGainLifeLostEffect(xValue, + "life equal to the number of Vampires you control"), false + ).addHint(hint) ); } @@ -55,46 +58,3 @@ public final class MalakirBloodwitch extends CardImpl { return new MalakirBloodwitch(this); } } - -class MalakirBloodwitchEffect extends OneShotEffect { - - MalakirBloodwitchEffect() { - super(Outcome.Benefit); - this.staticText = "each opponent loses life equal to the number of Vampires you control. You gain life equal to the life lost this way"; - } - - private MalakirBloodwitchEffect(final MalakirBloodwitchEffect effect) { - super(effect); - } - - @Override - public MalakirBloodwitchEffect copy() { - return new MalakirBloodwitchEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - if (player == null) { - return false; - } - - FilterControlledPermanent filter = new FilterControlledPermanent("Vampire"); - filter.add(SubType.VAMPIRE.getPredicate()); - int amount = game.getBattlefield().countAll(filter, source.getControllerId(), game); - Set opponents = game.getOpponents(source.getControllerId()); - - int total = 0; - for (UUID opponentUuid : opponents) { - Player opponent = game.getPlayer(opponentUuid); - if (opponent != null) { - total += opponent.loseLife(amount, game, source, false); - } - } - if (total > 0) { - player.gainLife(total, game, source); - } - - return true; - } -} diff --git a/Mage.Sets/src/mage/cards/o/ObNixilisOfTheBlackOath.java b/Mage.Sets/src/mage/cards/o/ObNixilisOfTheBlackOath.java index e06f4b0e732..ffd04bcef7c 100644 --- a/Mage.Sets/src/mage/cards/o/ObNixilisOfTheBlackOath.java +++ b/Mage.Sets/src/mage/cards/o/ObNixilisOfTheBlackOath.java @@ -1,24 +1,20 @@ - package mage.cards.o; -import java.util.UUID; -import mage.abilities.Ability; import mage.abilities.LoyaltyAbility; import mage.abilities.common.CanBeYourCommanderAbility; -import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.GetEmblemEffect; +import mage.abilities.effects.common.LoseLifeOpponentsYouGainLifeLostEffect; import mage.abilities.effects.common.LoseLifeSourceControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Outcome; import mage.constants.SuperType; -import mage.game.Game; import mage.game.command.emblems.ObNixilisOfTheBlackOathEmblem; import mage.game.permanent.token.DemonToken; -import mage.players.Player; + +import java.util.UUID; /** * @@ -34,7 +30,7 @@ public final class ObNixilisOfTheBlackOath extends CardImpl { this.setStartingLoyalty(3); // +2: Each opponent loses 1 life. You gain life equal to the life lost this way. - this.addAbility(new LoyaltyAbility(new ObNixilisOfTheBlackOathEffect1(), 2)); + this.addAbility(new LoyaltyAbility(new LoseLifeOpponentsYouGainLifeLostEffect(1), 2)); // -2: Create a 5/5 black Demon creature token with flying. You lose 2 life. LoyaltyAbility loyaltyAbility = new LoyaltyAbility(new CreateTokenEffect(new DemonToken()), -2); @@ -57,39 +53,3 @@ public final class ObNixilisOfTheBlackOath extends CardImpl { return new ObNixilisOfTheBlackOath(this); } } - -class ObNixilisOfTheBlackOathEffect1 extends OneShotEffect { - - public ObNixilisOfTheBlackOathEffect1() { - super(Outcome.Damage); - staticText = "Each opponent loses 1 life. You gain life equal to the life lost this way"; - } - - private ObNixilisOfTheBlackOathEffect1(final ObNixilisOfTheBlackOathEffect1 effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - int loseLife = 0; - for (UUID opponentId : game.getOpponents(source.getControllerId())) { - Player opponent = game.getPlayer(opponentId); - if (opponent != null) { - loseLife += opponent.loseLife(1, game, source, false); - } - } - controller.gainLife(loseLife, game, source); - return true; - - } - return false; - } - - @Override - public ObNixilisOfTheBlackOathEffect1 copy() { - return new ObNixilisOfTheBlackOathEffect1(this); - } - -} diff --git a/Mage.Sets/src/mage/cards/s/ScholarOfAthreos.java b/Mage.Sets/src/mage/cards/s/ScholarOfAthreos.java index 18f5bd164a1..43e93d72c24 100644 --- a/Mage.Sets/src/mage/cards/s/ScholarOfAthreos.java +++ b/Mage.Sets/src/mage/cards/s/ScholarOfAthreos.java @@ -1,19 +1,16 @@ package mage.cards.s; -import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.LoseLifeOpponentsYouGainLifeLostEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; import mage.constants.SubType; import mage.constants.Zone; -import mage.game.Game; -import mage.players.Player; + +import java.util.UUID; /** * @@ -30,7 +27,7 @@ public final class ScholarOfAthreos extends CardImpl { this.toughness = new MageInt(4); // {2}{B}: Each opponent loses 1 life. You gain life equal to the life lost this way. - this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new ScholarOfAthreosEffect(), new ManaCostsImpl<>("{2}{B}"))); + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new LoseLifeOpponentsYouGainLifeLostEffect(1), new ManaCostsImpl<>("{2}{B}"))); } private ScholarOfAthreos(final ScholarOfAthreos card) { @@ -42,34 +39,3 @@ public final class ScholarOfAthreos extends CardImpl { return new ScholarOfAthreos(this); } } - -class ScholarOfAthreosEffect extends OneShotEffect { - - ScholarOfAthreosEffect() { - super(Outcome.Damage); - staticText = "Each opponent loses 1 life. You gain life equal to the life lost this way"; - } - - private ScholarOfAthreosEffect(final ScholarOfAthreosEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - int lifeLost = 0; - for (UUID opponentId : game.getOpponents(source.getControllerId())) { - Player opponent = game.getPlayer(opponentId); - if(opponent != null) { - lifeLost += opponent.loseLife(1, game, source, false); - } - } - game.getPlayer(source.getControllerId()).gainLife(lifeLost, game, source); - return true; - } - - @Override - public ScholarOfAthreosEffect copy() { - return new ScholarOfAthreosEffect(this); - } - -} diff --git a/Mage.Sets/src/mage/cards/s/ServantOfTymaret.java b/Mage.Sets/src/mage/cards/s/ServantOfTymaret.java index 721cf512af3..52e171b52fa 100644 --- a/Mage.Sets/src/mage/cards/s/ServantOfTymaret.java +++ b/Mage.Sets/src/mage/cards/s/ServantOfTymaret.java @@ -1,21 +1,18 @@ - package mage.cards.s; -import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.LoseLifeOpponentsYouGainLifeLostEffect; import mage.abilities.effects.common.RegenerateSourceEffect; import mage.abilities.keyword.InspiredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Outcome; import mage.constants.Zone; -import mage.game.Game; + +import java.util.UUID; /** * @@ -31,7 +28,7 @@ public final class ServantOfTymaret extends CardImpl { this.toughness = new MageInt(3); // Inspired — Whenever Servant of Tymaret becomes untapped, each opponent loses 1 life. You gain life equal to the life lost this way. - this.addAbility(new InspiredAbility(new ServantOfTymaretEffect())); + this.addAbility(new InspiredAbility(new LoseLifeOpponentsYouGainLifeLostEffect(1))); // {2}{B}: Regenerate Servant of Tymaret. this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new RegenerateSourceEffect(), new ManaCostsImpl<>("{2}{B}"))); @@ -46,31 +43,3 @@ public final class ServantOfTymaret extends CardImpl { return new ServantOfTymaret(this); } } - -class ServantOfTymaretEffect extends OneShotEffect { - - ServantOfTymaretEffect() { - super(Outcome.Damage); - staticText = "each opponent loses 1 life. You gain life equal to the life lost this way"; - } - - private ServantOfTymaretEffect(final ServantOfTymaretEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - int lostAmount = 0; - for (UUID opponentId: game.getOpponents(source.getControllerId())) { - lostAmount += game.getPlayer(opponentId).loseLife(1, game, source, false); - } - game.getPlayer(source.getControllerId()).gainLife(lostAmount, game, source); - return true; - } - - @Override - public ServantOfTymaretEffect copy() { - return new ServantOfTymaretEffect(this); - } - -} diff --git a/Mage.Sets/src/mage/cards/s/Subversion.java b/Mage.Sets/src/mage/cards/s/Subversion.java index 261bb76d12e..0a8e0dfbd18 100644 --- a/Mage.Sets/src/mage/cards/s/Subversion.java +++ b/Mage.Sets/src/mage/cards/s/Subversion.java @@ -1,14 +1,11 @@ package mage.cards.s; -import mage.abilities.Ability; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.LoseLifeOpponentsYouGainLifeLostEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; import mage.constants.TargetController; -import mage.game.Game; import java.util.UUID; @@ -20,9 +17,8 @@ public final class Subversion extends CardImpl { public Subversion(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{B}{B}"); - // At the beginning of your upkeep, each opponent loses 1 life. You gain life equal to the life lost this way. - this.addAbility(new BeginningOfUpkeepTriggeredAbility(new SubversionEffect(), TargetController.YOU, false)); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new LoseLifeOpponentsYouGainLifeLostEffect(1), TargetController.YOU, false)); } private Subversion(final Subversion card) { @@ -34,32 +30,4 @@ public final class Subversion extends CardImpl { return new Subversion(this); } - - static class SubversionEffect extends OneShotEffect { - - public SubversionEffect() { - super(Outcome.Damage); - staticText = "each opponent loses 1 life. You gain life equal to the life lost this way"; - } - - private SubversionEffect(final SubversionEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - int damage = 0; - for (UUID opponentId : game.getOpponents(source.getControllerId())) { - damage += game.getPlayer(opponentId).damage(1, source.getSourceId(), source, game); - } - game.getPlayer(source.getControllerId()).gainLife(damage, game, source); - return true; - } - - @Override - public SubversionEffect copy() { - return new SubversionEffect(this); - } - - } } diff --git a/Mage.Sets/src/mage/cards/t/TormentedHero.java b/Mage.Sets/src/mage/cards/t/TormentedHero.java index 5ec33897200..9326e061300 100644 --- a/Mage.Sets/src/mage/cards/t/TormentedHero.java +++ b/Mage.Sets/src/mage/cards/t/TormentedHero.java @@ -1,18 +1,15 @@ - package mage.cards.t; -import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTappedAbility; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.LoseLifeOpponentsYouGainLifeLostEffect; import mage.abilities.keyword.HeroicAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Outcome; -import mage.game.Game; + +import java.util.UUID; /** * @@ -31,7 +28,7 @@ public final class TormentedHero extends CardImpl { // Tormented Hero enters the battlefield tapped. this.addAbility(new EntersBattlefieldTappedAbility()); // Heroic - Whenever you cast a spell that targets Tormented Hero, each opponent loses 1 life. You gain life equal to the life lost this way. - this.addAbility(new HeroicAbility(new EachOpponentLosesYouGainSumLifeEffect())); + this.addAbility(new HeroicAbility(new LoseLifeOpponentsYouGainLifeLostEffect(1))); } private TormentedHero(final TormentedHero card) { @@ -43,31 +40,3 @@ public final class TormentedHero extends CardImpl { return new TormentedHero(this); } } - -class EachOpponentLosesYouGainSumLifeEffect extends OneShotEffect { - - EachOpponentLosesYouGainSumLifeEffect() { - super(Outcome.Damage); - staticText = "Each opponent loses 1 life. You gain life equal to the life lost this way"; - } - - private EachOpponentLosesYouGainSumLifeEffect(final EachOpponentLosesYouGainSumLifeEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - int lostLife = 0; - for (UUID opponentId : game.getOpponents(source.getControllerId())) { - lostLife += game.getPlayer(opponentId).loseLife(1, game, source, false); - } - game.getPlayer(source.getControllerId()).gainLife(lostLife, game, source); - return true; - } - - @Override - public EachOpponentLosesYouGainSumLifeEffect copy() { - return new EachOpponentLosesYouGainSumLifeEffect(this); - } - -} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/ths/GrayMerchantOfAsphodelTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/ths/GrayMerchantOfAsphodelTest.java new file mode 100644 index 00000000000..b5bd4bc9855 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/ths/GrayMerchantOfAsphodelTest.java @@ -0,0 +1,42 @@ +package org.mage.test.cards.single.ths; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestMultiPlayerBase; + +/** + * @author xenohedron + */ +public class GrayMerchantOfAsphodelTest extends CardTestMultiPlayerBase { + + @Test + public void testDevotionLifeDrain() { + String gary = "Gray Merchant of Asphodel"; + // When Gray Merchant of Asphodel enters the battlefield, each opponent loses X life, + // where X is your devotion to black. You gain life equal to the life lost this way. + addCard(Zone.HAND, playerA, gary, 2); + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 10); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, gary); // 2 life lost, total 8 gained + + checkLife("", 1, PhaseStep.BEGIN_COMBAT, playerB, 18); + checkLife("", 1, PhaseStep.BEGIN_COMBAT, playerC, 20); // not in range + checkLife("", 1, PhaseStep.BEGIN_COMBAT, playerD, 18); + checkLife("", 1, PhaseStep.BEGIN_COMBAT, playerA, 24); + + castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, gary); // 4 life lost, total 8 gained + + setStrictChooseMode(true); + setStopAt(2, PhaseStep.UPKEEP); + execute(); + + assertLife(playerB, 14); + assertLife(playerC, 20); + assertLife(playerD, 14); + assertLife(playerA, 32); + + assertPermanentCount(playerA, gary, 2); + + } +} diff --git a/Mage/src/main/java/mage/abilities/effects/common/LoseLifeOpponentsYouGainLifeLostEffect.java b/Mage/src/main/java/mage/abilities/effects/common/LoseLifeOpponentsYouGainLifeLostEffect.java new file mode 100644 index 00000000000..6fa235c0e2b --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/LoseLifeOpponentsYouGainLifeLostEffect.java @@ -0,0 +1,63 @@ +package mage.abilities.effects.common; + +import mage.abilities.Ability; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.StaticValue; +import mage.abilities.effects.OneShotEffect; +import mage.constants.Outcome; +import mage.game.Game; +import mage.players.Player; + +import java.util.Objects; + +/** + * @author xenohedron + */ +public class LoseLifeOpponentsYouGainLifeLostEffect extends OneShotEffect { + + private final DynamicValue amount; + + public LoseLifeOpponentsYouGainLifeLostEffect(int amount) { + this(StaticValue.get(amount), amount + " life"); + } + + public LoseLifeOpponentsYouGainLifeLostEffect(DynamicValue amount, String amountLifeText) { + super(Outcome.GainLife); + this.amount = amount; + staticText = "each opponent loses " + amountLifeText + ". You gain life equal to the life lost this way"; + } + + protected LoseLifeOpponentsYouGainLifeLostEffect(final LoseLifeOpponentsYouGainLifeLostEffect effect) { + super(effect); + this.amount = effect.amount; + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return false; + } + int lifeToLose = amount.calculate(game, source, this); + if (lifeToLose < 1) { + return true; + } + int totalLifeLost = game + .getOpponents(source.getControllerId()) + .stream() + .map(game::getPlayer) + .filter(Objects::nonNull) + .mapToInt(opponent -> opponent.loseLife(lifeToLose, game, source, false)) + .sum(); + if (totalLifeLost > 1) { + controller.gainLife(totalLifeLost, game, source); + } + return true; + } + + @Override + public LoseLifeOpponentsYouGainLifeLostEffect copy() { + return new LoseLifeOpponentsYouGainLifeLostEffect(this); + } + +}