diff --git a/Mage.Sets/src/mage/cards/i/InfectiousCurse.java b/Mage.Sets/src/mage/cards/i/InfectiousCurse.java index 46e353fbd4d..f3e631dcb51 100644 --- a/Mage.Sets/src/mage/cards/i/InfectiousCurse.java +++ b/Mage.Sets/src/mage/cards/i/InfectiousCurse.java @@ -145,7 +145,7 @@ class InfectiousCurseCostReductionEffect extends CostModificationEffectImpl { allTargets = CardUtil.getAllPossibleTargets(abilityToModify, game); } - // try to reduce all the time (if it possible to target that player) + // try to reduce all the time (if it possible to target) return allTargets.stream().anyMatch(target -> Objects.equals(target, enchantment.getAttachedTo())); } diff --git a/Mage.Sets/src/mage/cards/k/KasminaEnigmaticMentor.java b/Mage.Sets/src/mage/cards/k/KasminaEnigmaticMentor.java index 21db376b546..fb2e41862b2 100644 --- a/Mage.Sets/src/mage/cards/k/KasminaEnigmaticMentor.java +++ b/Mage.Sets/src/mage/cards/k/KasminaEnigmaticMentor.java @@ -2,7 +2,6 @@ package mage.cards.k; import mage.abilities.Ability; import mage.abilities.LoyaltyAbility; -import mage.abilities.Mode; import mage.abilities.SpellAbility; import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility; import mage.abilities.common.SimpleStaticAbility; @@ -15,9 +14,11 @@ import mage.constants.*; import mage.game.Game; import mage.game.permanent.Permanent; import mage.game.permanent.token.WizardToken; -import mage.target.Target; +import mage.game.stack.Spell; import mage.util.CardUtil; +import java.util.Objects; +import java.util.Set; import java.util.UUID; /** @@ -33,7 +34,7 @@ public final class KasminaEnigmaticMentor extends CardImpl { this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(5)); // Spells your opponents cast that target a creature or planeswalker you control cost {2} more to cast. - this.addAbility(new SimpleStaticAbility(new KasminaEnigmaticMentorCostReductionEffect())); + this.addAbility(new SimpleStaticAbility(new KasminaEnigmaticMentorCostModificationEffect())); // -2: Create a 2/2 blue Wizard creature token. Draw a card, then discard a card. Ability ability = new LoyaltyAbility(new CreateTokenEffect(new WizardToken()), -2); @@ -53,49 +54,66 @@ public final class KasminaEnigmaticMentor extends CardImpl { } } -class KasminaEnigmaticMentorCostReductionEffect extends CostModificationEffectImpl { +class KasminaEnigmaticMentorCostModificationEffect extends CostModificationEffectImpl { - KasminaEnigmaticMentorCostReductionEffect() { + KasminaEnigmaticMentorCostModificationEffect() { super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.INCREASE_COST); staticText = "Spells your opponents cast that target a creature or planeswalker you control cost {2} more to cast"; } - private KasminaEnigmaticMentorCostReductionEffect(KasminaEnigmaticMentorCostReductionEffect effect) { + private KasminaEnigmaticMentorCostModificationEffect(KasminaEnigmaticMentorCostModificationEffect effect) { super(effect); } @Override public boolean apply(Game game, Ability source, Ability abilityToModify) { - SpellAbility spellAbility = (SpellAbility) abilityToModify; - CardUtil.adjustCost(spellAbility, -2); + CardUtil.increaseCost(abilityToModify, 2); return true; } @Override public boolean applies(Ability abilityToModify, Ability source, Game game) { - if (abilityToModify.getAbilityType() != AbilityType.SPELL - || !game.getOpponents(source.getControllerId()).contains(abilityToModify.getControllerId())) { + if (!(abilityToModify instanceof SpellAbility)) { return false; } - for (UUID modeId : abilityToModify.getModes().getSelectedModes()) { - Mode mode = abilityToModify.getModes().get(modeId); - for (Target target : mode.getTargets()) { - for (UUID targetUUID : target.getTargets()) { - Permanent permanent = game.getPermanent(targetUUID); - if (permanent != null - && (permanent.isCreature() || permanent.isPlaneswalker()) - && permanent.isControlledBy(source.getControllerId())) { - return true; - } - } - } + + if (!game.getOpponents(source.getControllerId()).contains(abilityToModify.getControllerId())) { + return false; } - return false; + + Spell spell = (Spell) game.getStack().getStackObject(abilityToModify.getId()); + Set allTargets; + if (spell != null) { + // real cast + allTargets = CardUtil.getAllSelectedTargets(abilityToModify, game); + } else { + // playable + allTargets = CardUtil.getAllPossibleTargets(abilityToModify, game); + + // can target without cost increase + if (allTargets.stream() + .map(game::getPermanent) + .filter(Objects::nonNull) + .anyMatch(permanent -> !isTargetCompatible(permanent, source))) { + return false; + } + ; + } + + return allTargets.stream() + .map(game::getPermanent) + .filter(Objects::nonNull) + .anyMatch(permanent -> isTargetCompatible(permanent, source)); + } + + private boolean isTargetCompatible(Permanent permanent, Ability source) { + // target a creature or planeswalker you control + return permanent.isControlledBy(source.getControllerId()) + && (permanent.isCreature() || permanent.isPlaneswalker()); } @Override - public KasminaEnigmaticMentorCostReductionEffect copy() { - return new KasminaEnigmaticMentorCostReductionEffect(this); + public KasminaEnigmaticMentorCostModificationEffect copy() { + return new KasminaEnigmaticMentorCostModificationEffect(this); } - } \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/k/KopalaWardenOfWaves.java b/Mage.Sets/src/mage/cards/k/KopalaWardenOfWaves.java index 1683c59aee7..6ca5365a8e3 100644 --- a/Mage.Sets/src/mage/cards/k/KopalaWardenOfWaves.java +++ b/Mage.Sets/src/mage/cards/k/KopalaWardenOfWaves.java @@ -1,31 +1,23 @@ - package mage.cards.k; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.Mode; +import mage.abilities.ActivatedAbility; import mage.abilities.SpellAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.common.cost.CostModificationEffectImpl; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.AbilityType; -import mage.constants.CardType; -import mage.constants.CostModificationType; -import mage.constants.Duration; -import mage.constants.Outcome; -import mage.constants.SubType; -import mage.constants.SuperType; -import mage.constants.Zone; -import mage.filter.common.FilterCreaturePermanent; +import mage.constants.*; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.target.Target; import mage.util.CardUtil; +import java.util.Objects; +import java.util.Set; +import java.util.UUID; + /** - * * @author TheElk801 */ public final class KopalaWardenOfWaves extends CardImpl { @@ -40,10 +32,10 @@ public final class KopalaWardenOfWaves extends CardImpl { this.toughness = new MageInt(2); // Spells your opponents cast that target a Merfolk you control cost {2} more to cast. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new KopalaWardenOfWavesCostReductionEffect())); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new KopalaWardenOfWavesCostModificationEffect1())); // Abilities your opponents activate that target a Merfolk you control cost {2} more to activate. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new KopalaWardenOfWavesCostReductionEffect2())); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new KopalaWardenOfWavesCostModificationEffect2())); } public KopalaWardenOfWaves(final KopalaWardenOfWaves card) { @@ -54,77 +46,51 @@ public final class KopalaWardenOfWaves extends CardImpl { public KopalaWardenOfWaves copy() { return new KopalaWardenOfWaves(this); } -} -class KopalaWardenOfWavesCostReductionEffect extends CostModificationEffectImpl { - - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("a Merfolk you control"); - private static final String effectText = "Spells your opponents cast that target a Merfolk you control cost {2} more to cast"; - - static { - filter.add(SubType.MERFOLK.getPredicate()); + static boolean isTargetCompatible(Permanent permanent, Ability source, Game game) { + // target a Merfolk you control + return permanent.isControlledBy(source.getControllerId()) + && permanent.hasSubtype(SubType.MERFOLK, game); } - KopalaWardenOfWavesCostReductionEffect() { - super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.INCREASE_COST); - staticText = effectText; - } - - KopalaWardenOfWavesCostReductionEffect(KopalaWardenOfWavesCostReductionEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source, Ability abilityToModify) { - SpellAbility spellAbility = (SpellAbility) abilityToModify; - CardUtil.adjustCost(spellAbility, -2); - return true; - } - - @Override - public boolean applies(Ability abilityToModify, Ability source, Game game) { - if (abilityToModify.getAbilityType() == AbilityType.SPELL) { - if (game.getOpponents(source.getControllerId()).contains(abilityToModify.getControllerId())) { - for (UUID modeId : abilityToModify.getModes().getSelectedModes()) { - Mode mode = abilityToModify.getModes().get(modeId); - for (Target target : mode.getTargets()) { - for (UUID targetUUID : target.getTargets()) { - Permanent creature = game.getPermanent(targetUUID); - if (creature != null - && filter.match(creature, game) - && creature.isControlledBy(source.getControllerId())) { - return true; - } - } - } - } - } + static boolean isAbilityCompatible(Ability abilityToModify, Ability source, Game game) { + if (!game.getOpponents(source.getControllerId()).contains(abilityToModify.getControllerId())) { + return false; } - return false; - } - @Override - public KopalaWardenOfWavesCostReductionEffect copy() { - return new KopalaWardenOfWavesCostReductionEffect(this); - } + Set allTargets; + if (game.getStack().getStackObject(abilityToModify.getId()) != null) { + // real cast + allTargets = CardUtil.getAllSelectedTargets(abilityToModify, game); + } else { + // playable + allTargets = CardUtil.getAllPossibleTargets(abilityToModify, game); + // can target without cost increase + if (allTargets.stream() + .map(game::getPermanent) + .filter(Objects::nonNull) + .anyMatch(permanent -> !isTargetCompatible(permanent, source, game))) { + return false; + } + ; + } + + return allTargets.stream() + .map(game::getPermanent) + .filter(Objects::nonNull) + .anyMatch(permanent -> isTargetCompatible(permanent, source, game)); + } } -class KopalaWardenOfWavesCostReductionEffect2 extends CostModificationEffectImpl { +class KopalaWardenOfWavesCostModificationEffect1 extends CostModificationEffectImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("a Merfolk you control"); - private static final String effectText = "Abilities your opponents activate that target a Merfolk you control cost {2} more to activate"; - - static { - filter.add(SubType.MERFOLK.getPredicate()); - } - - KopalaWardenOfWavesCostReductionEffect2() { + KopalaWardenOfWavesCostModificationEffect1() { super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.INCREASE_COST); - staticText = effectText; + this.staticText = "Spells your opponents cast that target a Merfolk you control cost {2} more to cast"; } - KopalaWardenOfWavesCostReductionEffect2(KopalaWardenOfWavesCostReductionEffect2 effect) { + KopalaWardenOfWavesCostModificationEffect1(KopalaWardenOfWavesCostModificationEffect1 effect) { super(effect); } @@ -136,26 +102,49 @@ class KopalaWardenOfWavesCostReductionEffect2 extends CostModificationEffectImpl @Override public boolean applies(Ability abilityToModify, Ability source, Game game) { - if (abilityToModify.getAbilityType() == AbilityType.ACTIVATED) { - if (game.getOpponents(source.getControllerId()).contains(abilityToModify.getControllerId())) { - for (Target target : abilityToModify.getTargets()) { - for (UUID targetUUID : target.getTargets()) { - Permanent creature = game.getPermanent(targetUUID); - if (creature != null - && filter.match(creature, game) - && creature.isControlledBy(source.getControllerId())) { - return true; - } - } - } - } + if (!(abilityToModify instanceof SpellAbility)) { + return false; } - return false; + + return KopalaWardenOfWaves.isAbilityCompatible(abilityToModify, source, game); } @Override - public KopalaWardenOfWavesCostReductionEffect2 copy() { - return new KopalaWardenOfWavesCostReductionEffect2(this); + public KopalaWardenOfWavesCostModificationEffect1 copy() { + return new KopalaWardenOfWavesCostModificationEffect1(this); + } + +} + +class KopalaWardenOfWavesCostModificationEffect2 extends CostModificationEffectImpl { + + KopalaWardenOfWavesCostModificationEffect2() { + super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.INCREASE_COST); + this.staticText = "Abilities your opponents activate that target a Merfolk you control cost {2} more to activate"; + } + + KopalaWardenOfWavesCostModificationEffect2(KopalaWardenOfWavesCostModificationEffect2 effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source, Ability abilityToModify) { + CardUtil.increaseCost(abilityToModify, 2); + return true; + } + + @Override + public boolean applies(Ability abilityToModify, Ability source, Game game) { + if (!(abilityToModify instanceof ActivatedAbility)) { + return false; + } + + return KopalaWardenOfWaves.isAbilityCompatible(abilityToModify, source, game); + } + + @Override + public KopalaWardenOfWavesCostModificationEffect2 copy() { + return new KopalaWardenOfWavesCostModificationEffect2(this); } } diff --git a/Mage.Sets/src/mage/cards/m/MonasterySiege.java b/Mage.Sets/src/mage/cards/m/MonasterySiege.java index 162abdd40c7..f72fc379d97 100644 --- a/Mage.Sets/src/mage/cards/m/MonasterySiege.java +++ b/Mage.Sets/src/mage/cards/m/MonasterySiege.java @@ -1,8 +1,6 @@ - package mage.cards.m; import mage.abilities.Ability; -import mage.abilities.Mode; import mage.abilities.SpellAbility; import mage.abilities.common.BeginningOfDrawTriggeredAbility; import mage.abilities.common.EntersBattlefieldAbility; @@ -17,19 +15,20 @@ import mage.cards.CardSetInfo; import mage.constants.*; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.target.Target; +import mage.game.stack.Spell; +import mage.players.Player; import mage.util.CardUtil; +import java.util.Set; import java.util.UUID; /** - * * @author emerald000 */ public final class MonasterySiege extends CardImpl { public MonasterySiege(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}"); // As Monastery Siege enters the battlefield, choose Khans or Dragons. this.addAbility(new EntersBattlefieldAbility(new ChooseModeEffect("Khans or Dragons?", "Khans", "Dragons"), null, @@ -57,6 +56,8 @@ public final class MonasterySiege extends CardImpl { class MonasterySiegeCostIncreaseEffect extends CostModificationEffectImpl { + private static ModeChoiceSourceCondition modeDragons = new ModeChoiceSourceCondition("Dragons"); + MonasterySiegeCostIncreaseEffect() { super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.INCREASE_COST); staticText = "• Dragons — Spells your opponents cast that target you or a permanent you control cost {2} more to cast"; @@ -68,33 +69,55 @@ class MonasterySiegeCostIncreaseEffect extends CostModificationEffectImpl { @Override public boolean apply(Game game, Ability source, Ability abilityToModify) { - SpellAbility spellAbility = (SpellAbility) abilityToModify; - CardUtil.adjustCost(spellAbility, -2); + CardUtil.increaseCost(abilityToModify, 2); return true; } @Override public boolean applies(Ability abilityToModify, Ability source, Game game) { - if (new ModeChoiceSourceCondition("Dragons").apply(game, source)) { - if (abilityToModify instanceof SpellAbility) { - if (game.getOpponents(source.getControllerId()).contains(abilityToModify.getControllerId())) { - for (UUID modeId : abilityToModify.getModes().getSelectedModes()) { - Mode mode = abilityToModify.getModes().get(modeId); - for (Target target : mode.getTargets()) { - for (UUID targetUUID : target.getTargets()) { - if (targetUUID.equals(source.getControllerId())) { - return true; - } - Permanent permanent = game.getPermanent(targetUUID); - if (permanent != null && permanent.isControlledBy(source.getControllerId())) { - return true; - } - } - } - } - } - } + if (!modeDragons.apply(game, source)) { + return false; } + + if (!(abilityToModify instanceof SpellAbility)) { + return false; + } + + if (!game.getOpponents(source.getControllerId()).contains(abilityToModify.getControllerId())) { + return false; + } + + Spell spell = (Spell) game.getStack().getStackObject(abilityToModify.getId()); + Set allTargets; + if (spell != null) { + // real cast + allTargets = CardUtil.getAllSelectedTargets(abilityToModify, game); + } else { + // playable + allTargets = CardUtil.getAllPossibleTargets(abilityToModify, game); + + // can target without cost increase + if (allTargets.stream().anyMatch(target -> !isTargetCompatible(target, source, game))) { + return false; + } + ; + } + + return allTargets.stream().anyMatch(target -> isTargetCompatible(target, source, game)); + } + + private boolean isTargetCompatible(UUID target, Ability source, Game game) { + // target you or a permanent you control + Player targetPlayer = game.getPlayer(target); + if (targetPlayer != null && targetPlayer.getId().equals(source.getControllerId())) { + return true; + } + + Permanent targetPermanent = game.getPermanent(target); + if (targetPermanent != null && targetPermanent.isControlledBy(source.getControllerId())) { + return true; + } + return false; } diff --git a/Mage.Sets/src/mage/cards/s/SenatorLottDod.java b/Mage.Sets/src/mage/cards/s/SenatorLottDod.java index e771d963c34..1301edcc49e 100644 --- a/Mage.Sets/src/mage/cards/s/SenatorLottDod.java +++ b/Mage.Sets/src/mage/cards/s/SenatorLottDod.java @@ -1,10 +1,7 @@ - package mage.cards.s; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.Mode; import mage.abilities.SpellAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.common.cost.CostModificationEffectImpl; @@ -13,12 +10,14 @@ import mage.cards.CardSetInfo; import mage.constants.*; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.game.stack.Spell; import mage.players.Player; -import mage.target.Target; import mage.util.CardUtil; +import java.util.Set; +import java.util.UUID; + /** - * * @author Styxo */ public final class SenatorLottDod extends CardImpl { @@ -32,11 +31,10 @@ public final class SenatorLottDod extends CardImpl { this.toughness = new MageInt(2); // Spells your opponents cast that target you cost {2} more to cast. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SenatorLottDodSpellsTargetingYouCostReductionEffect())); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SenatorLottDodSpellsTargetingYouCostModificationEffect())); // Spell your opponents cast that target a creature you control cost {1} more to cast. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SenatorLottDodSpellsTargetingCreatureCostReductionEffect())); - + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SenatorLottDodSpellsTargetingCreatureCostModificationEffect())); } public SenatorLottDod(final SenatorLottDod card) { @@ -49,14 +47,14 @@ public final class SenatorLottDod extends CardImpl { } } -class SenatorLottDodSpellsTargetingCreatureCostReductionEffect extends CostModificationEffectImpl { +class SenatorLottDodSpellsTargetingCreatureCostModificationEffect extends CostModificationEffectImpl { - public SenatorLottDodSpellsTargetingCreatureCostReductionEffect() { + public SenatorLottDodSpellsTargetingCreatureCostModificationEffect() { super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.INCREASE_COST); this.staticText = "Spell your opponents cast that target a creature you control cost {1} more to cast"; } - protected SenatorLottDodSpellsTargetingCreatureCostReductionEffect(SenatorLottDodSpellsTargetingCreatureCostReductionEffect effect) { + protected SenatorLottDodSpellsTargetingCreatureCostModificationEffect(SenatorLottDodSpellsTargetingCreatureCostModificationEffect effect) { super(effect); } @@ -68,38 +66,57 @@ class SenatorLottDodSpellsTargetingCreatureCostReductionEffect extends CostModif @Override public boolean applies(Ability abilityToModify, Ability source, Game game) { - if (abilityToModify instanceof SpellAbility) { - if (game.getOpponents(source.getControllerId()).contains(abilityToModify.getControllerId())) { - for (UUID modeId : abilityToModify.getModes().getSelectedModes()) { - Mode mode = abilityToModify.getModes().get(modeId); - for (Target target : mode.getTargets()) { - for (UUID targetUUID : target.getTargets()) { - Permanent permanent = game.getPermanent(targetUUID); - if (permanent != null && permanent.isControlledBy(source.getControllerId())) { - return true; - } - } - } - } - } + if (!(abilityToModify instanceof SpellAbility)) { + return false; } + + if (!game.getOpponents(source.getControllerId()).contains(abilityToModify.getControllerId())) { + return false; + } + + Spell spell = (Spell) game.getStack().getStackObject(abilityToModify.getId()); + Set allTargets; + if (spell != null) { + // real cast + allTargets = CardUtil.getAllSelectedTargets(abilityToModify, game); + } else { + // playable + allTargets = CardUtil.getAllPossibleTargets(abilityToModify, game); + + // can target without cost increase + if (allTargets.stream().anyMatch(target -> !isTargetCompatible(target, source, game))) { + return false; + } + ; + } + + return allTargets.stream().anyMatch(target -> isTargetCompatible(target, source, game)); + } + + private boolean isTargetCompatible(UUID target, Ability source, Game game) { + // target a creature you control + Permanent targetPermanent = game.getPermanent(target); + if (targetPermanent != null && targetPermanent.isCreature() && targetPermanent.isControlledBy(source.getControllerId())) { + return true; + } + return false; } @Override - public SenatorLottDodSpellsTargetingCreatureCostReductionEffect copy() { - return new SenatorLottDodSpellsTargetingCreatureCostReductionEffect(this); + public SenatorLottDodSpellsTargetingCreatureCostModificationEffect copy() { + return new SenatorLottDodSpellsTargetingCreatureCostModificationEffect(this); } } -class SenatorLottDodSpellsTargetingYouCostReductionEffect extends CostModificationEffectImpl { +class SenatorLottDodSpellsTargetingYouCostModificationEffect extends CostModificationEffectImpl { - public SenatorLottDodSpellsTargetingYouCostReductionEffect() { + public SenatorLottDodSpellsTargetingYouCostModificationEffect() { super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.INCREASE_COST); this.staticText = "Spells your opponents cast that target you cost {2} more to cast"; } - protected SenatorLottDodSpellsTargetingYouCostReductionEffect(SenatorLottDodSpellsTargetingYouCostReductionEffect effect) { + protected SenatorLottDodSpellsTargetingYouCostModificationEffect(SenatorLottDodSpellsTargetingYouCostModificationEffect effect) { super(effect); } @@ -111,26 +128,45 @@ class SenatorLottDodSpellsTargetingYouCostReductionEffect extends CostModificati @Override public boolean applies(Ability abilityToModify, Ability source, Game game) { - if (abilityToModify instanceof SpellAbility) { - if (game.getOpponents(source.getControllerId()).contains(abilityToModify.getControllerId())) { - for (UUID modeId : abilityToModify.getModes().getSelectedModes()) { - Mode mode = abilityToModify.getModes().get(modeId); - for (Target target : mode.getTargets()) { - for (UUID targetUUID : target.getTargets()) { - Player player = game.getPlayer(targetUUID); - if (player != null && player.getId().equals(source.getControllerId())) { - return true; - } - } - } - } - } + if (!(abilityToModify instanceof SpellAbility)) { + return false; } + + if (!game.getOpponents(source.getControllerId()).contains(abilityToModify.getControllerId())) { + return false; + } + + Spell spell = (Spell) game.getStack().getStackObject(abilityToModify.getId()); + Set allTargets; + if (spell != null) { + // real cast + allTargets = CardUtil.getAllSelectedTargets(abilityToModify, game); + } else { + // playable + allTargets = CardUtil.getAllPossibleTargets(abilityToModify, game); + + // can target without cost increase + if (allTargets.stream().anyMatch(target -> !isTargetCompatible(target, source, game))) { + return false; + } + ; + } + + return allTargets.stream().anyMatch(target -> isTargetCompatible(target, source, game)); + } + + private boolean isTargetCompatible(UUID target, Ability source, Game game) { + // target you + Player targetPlayer = game.getPlayer(target); + if (targetPlayer != null && targetPlayer.getId().equals(source.getControllerId())) { + return true; + } + return false; } @Override - public SenatorLottDodSpellsTargetingYouCostReductionEffect copy() { - return new SenatorLottDodSpellsTargetingYouCostReductionEffect(this); + public SenatorLottDodSpellsTargetingYouCostModificationEffect copy() { + return new SenatorLottDodSpellsTargetingYouCostModificationEffect(this); } } diff --git a/Mage.Sets/src/mage/cards/t/TerrorOfThePeaks.java b/Mage.Sets/src/mage/cards/t/TerrorOfThePeaks.java index 93eadfdf00f..a27527b2a2a 100644 --- a/Mage.Sets/src/mage/cards/t/TerrorOfThePeaks.java +++ b/Mage.Sets/src/mage/cards/t/TerrorOfThePeaks.java @@ -2,7 +2,6 @@ package mage.cards.t; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.Mode; import mage.abilities.SpellAbility; import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; @@ -17,10 +16,12 @@ import mage.filter.StaticFilters; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; -import mage.target.Target; +import mage.game.stack.Spell; import mage.target.common.TargetAnyTarget; +import mage.util.CardUtil; -import java.util.Collection; +import java.util.Objects; +import java.util.Set; import java.util.UUID; /** @@ -59,7 +60,7 @@ class TerrorOfThePeaksCostIncreaseEffect extends CostModificationEffectImpl { TerrorOfThePeaksCostIncreaseEffect() { super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.INCREASE_COST); - staticText = "Spells your opponents cast that target {this} cost an additional 3 life to cast"; + this.staticText = "Spells your opponents cast that target {this} cost an additional 3 life to cast"; } private TerrorOfThePeaksCostIncreaseEffect(TerrorOfThePeaksCostIncreaseEffect effect) { @@ -68,27 +69,42 @@ class TerrorOfThePeaksCostIncreaseEffect extends CostModificationEffectImpl { @Override public boolean apply(Game game, Ability source, Ability abilityToModify) { - SpellAbility spellAbility = (SpellAbility) abilityToModify; - spellAbility.addCost(new PayLifeCost(3)); + abilityToModify.addCost(new PayLifeCost(3)); return true; } @Override public boolean applies(Ability abilityToModify, Ability source, Game game) { - if (!(abilityToModify instanceof SpellAbility) - || !game.getOpponents(source.getControllerId()).contains(abilityToModify.getControllerId())) { + if (!(abilityToModify instanceof SpellAbility)) { return false; } - return abilityToModify - .getModes() - .getSelectedModes() - .stream() - .map(uuid -> abilityToModify.getModes().get(uuid)) - .map(Mode::getTargets) - .flatMap(Collection::stream) - .map(Target::getTargets) - .flatMap(Collection::stream) - .anyMatch(uuid -> uuid.equals(source.getSourceId())); + + if (!game.getOpponents(source.getControllerId()).contains(abilityToModify.getControllerId())) { + return false; + } + + Spell spell = (Spell) game.getStack().getStackObject(abilityToModify.getId()); + Set allTargets; + if (spell != null) { + // real cast + allTargets = CardUtil.getAllSelectedTargets(abilityToModify, game); + } else { + // playable + allTargets = CardUtil.getAllPossibleTargets(abilityToModify, game); + + // can target without cost increase + if (allTargets.stream().anyMatch(target -> !isTargetCompatible(target, source, game))) { + return false; + } + ; + } + + return allTargets.stream().anyMatch(target -> isTargetCompatible(target, source, game)); + } + + private boolean isTargetCompatible(UUID target, Ability source, Game game) { + // target {this} + return Objects.equals(source.getSourceId(), target); } @Override diff --git a/Mage/src/main/java/mage/abilities/effects/common/cost/SpellsCostModificationThatTargetSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/cost/SpellsCostModificationThatTargetSourceEffect.java index 3364e3c02ad..e8fbeb1c1da 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/cost/SpellsCostModificationThatTargetSourceEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/cost/SpellsCostModificationThatTargetSourceEffect.java @@ -1,19 +1,20 @@ package mage.abilities.effects.common.cost; -import java.util.Set; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.SpellAbility; +import mage.cards.Card; import mage.constants.CostModificationType; import mage.constants.Duration; import mage.constants.Outcome; import mage.constants.TargetController; import mage.filter.FilterCard; import mage.game.Game; -import mage.game.stack.Spell; import mage.players.Player; import mage.util.CardUtil; +import java.util.Set; +import java.util.UUID; + /** * @author JayDi85 */ @@ -111,21 +112,25 @@ public class SpellsCostModificationThatTargetSourceEffect extends CostModificati return false; } - Spell spell = (Spell) game.getStack().getStackObject(abilityToModify.getId()); - if (spell != null && this.spellFilter.match(spell, game)) { - // real cast with put on stack + Card spellCard = ((SpellAbility) abilityToModify).getCharacteristics(game); + if (spellCard == null || !this.spellFilter.match(spellCard, game)) { + return false; + } + + if (game.getStack().getStackObject(abilityToModify.getId()) != null) { + // real cast Set allTargets = CardUtil.getAllSelectedTargets(abilityToModify, game); return allTargets.contains(source.getSourceId()); } else { - // get playable and other staff without put on stack - // used at least for flashback ability because Flashback ability doesn't use stack + // playable Set allTargets = CardUtil.getAllPossibleTargets(abilityToModify, game); + switch (this.getModificationType()) { case REDUCE_COST: - // reduce all the time + // must reduce all the time return allTargets.contains(source.getSourceId()); case INCREASE_COST: - // increase if can't target another (e.g. user can choose another target without cost increase) + // must increase if can't target another (e.g. user can choose another target without cost increase) return allTargets.contains(source.getSourceId()) && allTargets.size() <= 1; } }