diff --git a/Mage.Sets/src/mage/cards/a/ArcticFoxes.java b/Mage.Sets/src/mage/cards/a/ArcticFoxes.java index b658e56e0e..d6b86a7d42 100644 --- a/Mage.Sets/src/mage/cards/a/ArcticFoxes.java +++ b/Mage.Sets/src/mage/cards/a/ArcticFoxes.java @@ -68,6 +68,6 @@ enum ArcticFoxesCondition implements Condition { if (defenderId == null) { return false; } - return game.getBattlefield().contains(filter, defenderId, 1, game); + return game.getBattlefield().contains(filter, source.getSourceId(), defenderId, game, 1); } } \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/c/CityInABottle.java b/Mage.Sets/src/mage/cards/c/CityInABottle.java index 8a570d692a..0d36c7ffbc 100644 --- a/Mage.Sets/src/mage/cards/c/CityInABottle.java +++ b/Mage.Sets/src/mage/cards/c/CityInABottle.java @@ -1,8 +1,5 @@ package mage.cards.c; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.StateTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; @@ -11,7 +8,6 @@ import mage.abilities.effects.OneShotEffect; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import static mage.cards.c.CityInABottle.getArabianNightsNamePredicates; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Outcome; @@ -23,11 +19,15 @@ import mage.filter.predicate.mageobject.NamePredicate; import mage.filter.predicate.permanent.TokenPredicate; import mage.game.Game; import mage.game.events.GameEvent; -import mage.game.events.GameEvent.EventType; import mage.game.permanent.Permanent; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +import static mage.cards.c.CityInABottle.getArabianNightsNamePredicates; + /** - * * @author emerald000 */ public final class CityInABottle extends CardImpl { @@ -158,7 +158,7 @@ class CityInABottleStateTriggeredAbility extends StateTriggeredAbility { @Override public boolean checkTrigger(GameEvent event, Game game) { - return game.getBattlefield().contains(filter, this.getControllerId(), game, 1); + return game.getBattlefield().contains(filter, this.getSourceId(), this.getControllerId(), game, 1); } @Override diff --git a/Mage.Sets/src/mage/cards/c/ConcertedEffort.java b/Mage.Sets/src/mage/cards/c/ConcertedEffort.java index 3d17beca5d..cd7ddf4724 100644 --- a/Mage.Sets/src/mage/cards/c/ConcertedEffort.java +++ b/Mage.Sets/src/mage/cards/c/ConcertedEffort.java @@ -1,7 +1,5 @@ - package mage.cards.c; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.effects.OneShotEffect; @@ -18,14 +16,15 @@ import mage.filter.predicate.mageobject.AbilityPredicate; import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.UUID; + /** - * * @author emerald000 */ public final class ConcertedEffort extends CardImpl { public ConcertedEffort(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{W}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}{W}"); // At the beginning of each upkeep, creatures you control gain flying until end of turn if a creature you control has flying. The same is true for fear, first strike, double strike, landwalk, protection, trample, and vigilance. this.addAbility(new BeginningOfUpkeepTriggeredAbility(new ConcertedEffortEffect(), TargetController.ANY, false)); @@ -81,22 +80,22 @@ class ConcertedEffortEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { // Flying - if (game.getBattlefield().contains(filterFlying, source.getControllerId(), 1, game)) { + if (game.getBattlefield().contains(filterFlying, source, game, 1)) { game.addEffect(new GainAbilityControlledEffect(FlyingAbility.getInstance(), Duration.EndOfTurn, filterCreatures), source); } // Fear - if (game.getBattlefield().contains(filterFear, source.getControllerId(), 1, game)) { + if (game.getBattlefield().contains(filterFear, source, game, 1)) { game.addEffect(new GainAbilityControlledEffect(FearAbility.getInstance(), Duration.EndOfTurn, filterCreatures), source); } // First strike - if (game.getBattlefield().contains(filterFirstStrike, source.getControllerId(), 1, game)) { + if (game.getBattlefield().contains(filterFirstStrike, source, game, 1)) { game.addEffect(new GainAbilityControlledEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn, filterCreatures), source); } // Double strike - if (game.getBattlefield().contains(filterDoubleStrike, source.getControllerId(), 1, game)) { + if (game.getBattlefield().contains(filterDoubleStrike, source, game, 1)) { game.addEffect(new GainAbilityControlledEffect(DoubleStrikeAbility.getInstance(), Duration.EndOfTurn, filterCreatures), source); } @@ -119,12 +118,12 @@ class ConcertedEffortEffect extends OneShotEffect { } // Trample - if (game.getBattlefield().contains(filterTrample, source.getControllerId(), 1, game)) { + if (game.getBattlefield().contains(filterTrample, source, game, 1)) { game.addEffect(new GainAbilityControlledEffect(TrampleAbility.getInstance(), Duration.EndOfTurn, filterCreatures), source); } // Vigilance - if (game.getBattlefield().contains(filterVigilance, source.getControllerId(), 1, game)) { + if (game.getBattlefield().contains(filterVigilance, source, game, 1)) { game.addEffect(new GainAbilityControlledEffect(VigilanceAbility.getInstance(), Duration.EndOfTurn, filterCreatures), source); } return true; diff --git a/Mage.Sets/src/mage/cards/c/CullingScales.java b/Mage.Sets/src/mage/cards/c/CullingScales.java index 5c8a890a79..4917bc673b 100644 --- a/Mage.Sets/src/mage/cards/c/CullingScales.java +++ b/Mage.Sets/src/mage/cards/c/CullingScales.java @@ -1,7 +1,5 @@ - package mage.cards.c; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.effects.common.DestroyTargetEffect; @@ -12,27 +10,30 @@ import mage.constants.ComparisonType; import mage.constants.TargetController; import mage.filter.FilterPermanent; import mage.filter.common.FilterNonlandPermanent; -import mage.filter.predicate.Predicate; +import mage.filter.predicate.ObjectSourcePlayer; +import mage.filter.predicate.ObjectSourcePlayerPredicate; import mage.filter.predicate.mageobject.ConvertedManaCostPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.TargetPermanent; +import java.util.UUID; + /** - * * @author cg5 */ public final class CullingScales extends CardImpl { private static final FilterPermanent filterNonlandPermanentWithLowestCmc = new FilterNonlandPermanent( - "nonland permanent with the lowest converted mana cost (If two or more permanents are tied for lowest cost, target any one of them.)" + "nonland permanent with the lowest converted mana cost (If two or more permanents are tied for lowest cost, target any one of them.)" ); + static { filterNonlandPermanentWithLowestCmc.add(new HasLowestCMCAmongstNonlandPermanentsPredicate()); } - + public CullingScales(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{3}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); // At the beginning of your upkeep, destroy target nonland permanent with the lowest converted mana cost. Ability ability = new BeginningOfUpkeepTriggeredAbility(new DestroyTargetEffect(), TargetController.YOU, false); @@ -48,16 +49,16 @@ public final class CullingScales extends CardImpl { public CullingScales copy() { return new CullingScales(this); } - + } -class HasLowestCMCAmongstNonlandPermanentsPredicate implements Predicate { - +class HasLowestCMCAmongstNonlandPermanentsPredicate implements ObjectSourcePlayerPredicate> { + @Override - public boolean apply(Permanent input, Game game) { + public boolean apply(ObjectSourcePlayer input, Game game) { FilterPermanent filter = new FilterNonlandPermanent(); - filter.add(new ConvertedManaCostPredicate(ComparisonType.FEWER_THAN, input.getConvertedManaCost())); - return !game.getBattlefield().contains(filter, 1, game); + filter.add(new ConvertedManaCostPredicate(ComparisonType.FEWER_THAN, input.getObject().getConvertedManaCost())); + return !game.getBattlefield().contains(filter, input.getSourceId(), input.getPlayerId(), game, 1); } - + } \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/d/DoomForetold.java b/Mage.Sets/src/mage/cards/d/DoomForetold.java index 294e46acda..090c663cc4 100644 --- a/Mage.Sets/src/mage/cards/d/DoomForetold.java +++ b/Mage.Sets/src/mage/cards/d/DoomForetold.java @@ -84,7 +84,7 @@ class DoomForetoldEffect extends OneShotEffect { } FilterPermanent filter2 = filter.copy(); filter2.add(new ControllerIdPredicate(player.getId())); - if (game.getBattlefield().contains(filter2, 1, game)) { + if (game.getBattlefield().contains(filter2, source, game, 1)) { TargetPermanent target = new TargetPermanent(filter2); target.setNotTarget(true); if (player.choose(Outcome.Sacrifice, target, source.getSourceId(), game)) { diff --git a/Mage.Sets/src/mage/cards/h/HedronAlignment.java b/Mage.Sets/src/mage/cards/h/HedronAlignment.java index 2468d05c77..c825a61407 100644 --- a/Mage.Sets/src/mage/cards/h/HedronAlignment.java +++ b/Mage.Sets/src/mage/cards/h/HedronAlignment.java @@ -1,7 +1,5 @@ - package mage.cards.h; -import java.util.UUID; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; @@ -24,14 +22,15 @@ import mage.filter.predicate.mageobject.NamePredicate; import mage.game.Game; import mage.players.Player; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class HedronAlignment extends CardImpl { public HedronAlignment(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}"); // Hexproof this.addAbility(HexproofAbility.getInstance()); @@ -85,7 +84,7 @@ class HedronAlignmentEffect extends OneShotEffect { Cards cardsToReveal = new CardsImpl(); controller.revealCards(sourceObject.getIdName(), cardsToReveal, game); // Check battlefield - if (!game.getBattlefield().contains(filterPermanent, source.getControllerId(), game, 1)) { + if (!game.getBattlefield().contains(filterPermanent, source, game, 1)) { return true; } if (controller.getHand().getCards(filterCard, source.getSourceId(), controller.getId(), game).isEmpty()) { diff --git a/Mage.Sets/src/mage/cards/h/HeraldOfLeshrac.java b/Mage.Sets/src/mage/cards/h/HeraldOfLeshrac.java index 9545ca7f1e..7425917715 100644 --- a/Mage.Sets/src/mage/cards/h/HeraldOfLeshrac.java +++ b/Mage.Sets/src/mage/cards/h/HeraldOfLeshrac.java @@ -1,7 +1,5 @@ - package mage.cards.h; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.LeavesBattlefieldTriggeredAbility; @@ -17,12 +15,7 @@ import mage.abilities.keyword.CumulativeUpkeepAbility; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.SubType; -import mage.constants.Duration; -import mage.constants.Outcome; -import mage.constants.TargetController; -import mage.constants.Zone; +import mage.constants.*; import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledLandPermanent; import mage.filter.common.FilterLandPermanent; @@ -34,13 +27,15 @@ import mage.target.Target; import mage.target.TargetPermanent; import mage.target.targetpointer.FixedTarget; +import java.util.UUID; + /** - * * @author emerald000 */ public final class HeraldOfLeshrac extends CardImpl { private static final FilterPermanent filter = new FilterControlledLandPermanent("land you control but don't own"); + static { filter.add(TargetController.NOT_YOU.getOwnerPredicate()); } @@ -78,6 +73,7 @@ public final class HeraldOfLeshrac extends CardImpl { class HeraldOfLeshracCumulativeCost extends CostImpl { private static final FilterPermanent filter = new FilterLandPermanent("land you don't control"); + static { filter.add(TargetController.NOT_YOU.getControllerPredicate()); } @@ -105,7 +101,7 @@ class HeraldOfLeshracCumulativeCost extends CostImpl { @Override public boolean canPay(Ability ability, Ability source, UUID controllerId, Game game) { - return game.getBattlefield().contains(filter, controllerId, game, 1); + return game.getBattlefield().contains(filter, source.getSourceId(), controllerId, game, 1); } @Override diff --git a/Mage.Sets/src/mage/cards/m/MajesticMyriarch.java b/Mage.Sets/src/mage/cards/m/MajesticMyriarch.java index 847eb1ed20..c0475fb234 100644 --- a/Mage.Sets/src/mage/cards/m/MajesticMyriarch.java +++ b/Mage.Sets/src/mage/cards/m/MajesticMyriarch.java @@ -103,62 +103,62 @@ class MajesticMyriarchEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { // Flying - if (game.getBattlefield().contains(filterFlying, source.getControllerId(), 1, game)) { + if (game.getBattlefield().containsControlled(filterFlying, source, game, 1)) { game.addEffect(new GainAbilitySourceEffect(FlyingAbility.getInstance(), Duration.EndOfTurn), source); } // First strike - if (game.getBattlefield().contains(filterFirstStrike, source.getControllerId(), 1, game)) { + if (game.getBattlefield().containsControlled(filterFirstStrike, source, game, 1)) { game.addEffect(new GainAbilitySourceEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn), source); } // Double strike - if (game.getBattlefield().contains(filterDoubleStrike, source.getControllerId(), 1, game)) { + if (game.getBattlefield().containsControlled(filterDoubleStrike, source, game, 1)) { game.addEffect(new GainAbilitySourceEffect(DoubleStrikeAbility.getInstance(), Duration.EndOfTurn), source); } // Deathtouch - if (game.getBattlefield().contains(filterDeathtouch, source.getControllerId(), 1, game)) { + if (game.getBattlefield().containsControlled(filterDeathtouch, source, game, 1)) { game.addEffect(new GainAbilitySourceEffect(DeathtouchAbility.getInstance(), Duration.EndOfTurn), source); } // Haste - if (game.getBattlefield().contains(filterHaste, source.getControllerId(), 1, game)) { + if (game.getBattlefield().containsControlled(filterHaste, source, game, 1)) { game.addEffect(new GainAbilitySourceEffect(HasteAbility.getInstance(), Duration.EndOfTurn), source); } // Hexproof - if (game.getBattlefield().contains(filterHexproof, source.getControllerId(), 1, game)) { + if (game.getBattlefield().containsControlled(filterHexproof, source, game, 1)) { game.addEffect(new GainAbilitySourceEffect(HexproofAbility.getInstance(), Duration.EndOfTurn), source); } // Indestructible - if (game.getBattlefield().contains(filterIndestructible, source.getControllerId(), 1, game)) { + if (game.getBattlefield().containsControlled(filterIndestructible, source, game, 1)) { game.addEffect(new GainAbilitySourceEffect(IndestructibleAbility.getInstance(), Duration.EndOfTurn), source); } // Lifelink - if (game.getBattlefield().contains(filterLifelink, source.getControllerId(), 1, game)) { + if (game.getBattlefield().containsControlled(filterLifelink, source, game, 1)) { game.addEffect(new GainAbilitySourceEffect(LifelinkAbility.getInstance(), Duration.EndOfTurn), source); } // Menace - if (game.getBattlefield().contains(filterMenace, source.getControllerId(), 1, game)) { + if (game.getBattlefield().containsControlled(filterMenace, source, game, 1)) { game.addEffect(new GainAbilitySourceEffect(new MenaceAbility(), Duration.EndOfTurn), source); } // Reach - if (game.getBattlefield().contains(filterReach, source.getControllerId(), 1, game)) { + if (game.getBattlefield().containsControlled(filterReach, source, game, 1)) { game.addEffect(new GainAbilitySourceEffect(ReachAbility.getInstance(), Duration.EndOfTurn), source); } // Trample - if (game.getBattlefield().contains(filterTrample, source.getControllerId(), 1, game)) { + if (game.getBattlefield().containsControlled(filterTrample, source, game, 1)) { game.addEffect(new GainAbilitySourceEffect(TrampleAbility.getInstance(), Duration.EndOfTurn), source); } // Vigilance - if (game.getBattlefield().contains(filterVigilance, source.getControllerId(), 1, game)) { + if (game.getBattlefield().containsControlled(filterVigilance, source, game, 1)) { game.addEffect(new GainAbilitySourceEffect(VigilanceAbility.getInstance(), Duration.EndOfTurn), source); } return true; diff --git a/Mage.Sets/src/mage/cards/o/OdricLunarchMarshal.java b/Mage.Sets/src/mage/cards/o/OdricLunarchMarshal.java index bd0a2c6af4..34781787fe 100644 --- a/Mage.Sets/src/mage/cards/o/OdricLunarchMarshal.java +++ b/Mage.Sets/src/mage/cards/o/OdricLunarchMarshal.java @@ -1,4 +1,3 @@ - package mage.cards.o; import mage.MageInt; @@ -94,67 +93,67 @@ class OdricLunarchMarshalEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { // First strike - if (game.getBattlefield().contains(filterFirstStrike, source.getControllerId(), 1, game)) { + if (game.getBattlefield().containsControlled(filterFirstStrike, source, game, 1)) { game.addEffect(new GainAbilityControlledEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn, filterCreatures), source); } // Flying - if (game.getBattlefield().contains(filterFlying, source.getControllerId(), 1, game)) { + if (game.getBattlefield().containsControlled(filterFlying, source, game, 1)) { game.addEffect(new GainAbilityControlledEffect(FlyingAbility.getInstance(), Duration.EndOfTurn, filterCreatures), source); } // Deathtouch - if (game.getBattlefield().contains(filterDeathtouch, source.getControllerId(), 1, game)) { + if (game.getBattlefield().containsControlled(filterDeathtouch, source, game, 1)) { game.addEffect(new GainAbilityControlledEffect(DeathtouchAbility.getInstance(), Duration.EndOfTurn, filterCreatures), source); } // Double strike - if (game.getBattlefield().contains(filterDoubleStrike, source.getControllerId(), 1, game)) { + if (game.getBattlefield().containsControlled(filterDoubleStrike, source, game, 1)) { game.addEffect(new GainAbilityControlledEffect(DoubleStrikeAbility.getInstance(), Duration.EndOfTurn, filterCreatures), source); } // Haste - if (game.getBattlefield().contains(filterHaste, source.getControllerId(), 1, game)) { + if (game.getBattlefield().containsControlled(filterHaste, source, game, 1)) { game.addEffect(new GainAbilityControlledEffect(HasteAbility.getInstance(), Duration.EndOfTurn, filterCreatures), source); } // Hexproof - if (game.getBattlefield().contains(filterHexproof, source.getControllerId(), 1, game)) { + if (game.getBattlefield().containsControlled(filterHexproof, source, game, 1)) { game.addEffect(new GainAbilityControlledEffect(HexproofAbility.getInstance(), Duration.EndOfTurn, filterCreatures), source); } // Indestructible - if (game.getBattlefield().contains(filterIndestructible, source.getControllerId(), 1, game)) { + if (game.getBattlefield().containsControlled(filterIndestructible, source, game, 1)) { game.addEffect(new GainAbilityControlledEffect(IndestructibleAbility.getInstance(), Duration.EndOfTurn, filterCreatures), source); } // Lifelink - if (game.getBattlefield().contains(filterLifelink, source.getControllerId(), 1, game)) { + if (game.getBattlefield().containsControlled(filterLifelink, source, game, 1)) { game.addEffect(new GainAbilityControlledEffect(LifelinkAbility.getInstance(), Duration.EndOfTurn, filterCreatures), source); } // Menace - if (game.getBattlefield().contains(filterMenace, source.getControllerId(), 1, game)) { + if (game.getBattlefield().containsControlled(filterMenace, source, game, 1)) { game.addEffect(new GainAbilityControlledEffect(new MenaceAbility(), Duration.EndOfTurn, filterCreatures), source); } // Reach - if (game.getBattlefield().contains(filterReach, source.getControllerId(), 1, game)) { + if (game.getBattlefield().containsControlled(filterReach, source, game, 1)) { game.addEffect(new GainAbilityControlledEffect(ReachAbility.getInstance(), Duration.EndOfTurn, filterCreatures), source); } // Skulk - if (game.getBattlefield().contains(filterSkulk, source.getControllerId(), 1, game)) { + if (game.getBattlefield().containsControlled(filterSkulk, source, game, 1)) { game.addEffect(new GainAbilityControlledEffect(new SkulkAbility(), Duration.EndOfTurn, filterCreatures), source); } // Trample - if (game.getBattlefield().contains(filterTrample, source.getControllerId(), 1, game)) { + if (game.getBattlefield().containsControlled(filterTrample, source, game, 1)) { game.addEffect(new GainAbilityControlledEffect(TrampleAbility.getInstance(), Duration.EndOfTurn, filterCreatures), source); } // Vigilance - if (game.getBattlefield().contains(filterVigilance, source.getControllerId(), 1, game)) { + if (game.getBattlefield().containsControlled(filterVigilance, source, game, 1)) { game.addEffect(new GainAbilityControlledEffect(VigilanceAbility.getInstance(), Duration.EndOfTurn, filterCreatures), source); } return true; diff --git a/Mage.Sets/src/mage/cards/r/RemorselessPunishment.java b/Mage.Sets/src/mage/cards/r/RemorselessPunishment.java index 886c612107..e537dac680 100644 --- a/Mage.Sets/src/mage/cards/r/RemorselessPunishment.java +++ b/Mage.Sets/src/mage/cards/r/RemorselessPunishment.java @@ -1,7 +1,5 @@ - package mage.cards.r; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; import mage.cards.CardImpl; @@ -16,14 +14,15 @@ import mage.players.Player; import mage.target.TargetPermanent; import mage.target.common.TargetOpponent; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class RemorselessPunishment extends CardImpl { public RemorselessPunishment(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{3}{B}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{B}{B}"); // Target opponent loses 5 life unless that player discards two cards or sacrifices a creature or planeswalker. Repeat this process once. getSpellAbility().addEffect(new RemorselessPunishmentEffect()); @@ -80,7 +79,7 @@ class RemorselessPunishmentEffect extends OneShotEffect { return; } } - if (game.getBattlefield().contains(filter, opponent.getId(), 1, game)) { + if (game.getBattlefield().containsControlled(filter, source.getSourceId(), opponent.getId(), game, 1)) { if (opponent.chooseUse(outcome, "Choose your " + iteration + " punishment.", null, "Sacrifice a creature or planeswalker", "Lose 5 life", source, game)) { TargetPermanent target = new TargetPermanent(1, 1, filter, true); if (target.choose(Outcome.Sacrifice, opponent.getId(), source.getId(), game)) { diff --git a/Mage.Sets/src/mage/cards/s/ShelteringAncient.java b/Mage.Sets/src/mage/cards/s/ShelteringAncient.java index 272bbc5e05..531688db7b 100644 --- a/Mage.Sets/src/mage/cards/s/ShelteringAncient.java +++ b/Mage.Sets/src/mage/cards/s/ShelteringAncient.java @@ -1,7 +1,5 @@ - package mage.cards.s; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.costs.Cost; @@ -11,8 +9,8 @@ import mage.abilities.keyword.TrampleAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Outcome; +import mage.constants.SubType; import mage.constants.TargetController; import mage.counters.CounterType; import mage.filter.common.FilterCreaturePermanent; @@ -22,8 +20,9 @@ import mage.players.Player; import mage.target.Target; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author emerald000 */ public final class ShelteringAncient extends CardImpl { @@ -82,7 +81,7 @@ class ShelteringAncientCost extends CostImpl { @Override public boolean canPay(Ability ability, Ability source, UUID controllerId, Game game) { - return game.getBattlefield().contains(filter, source.getSourceId(), game, 1); + return game.getBattlefield().contains(filter, source, game, 1); } @Override diff --git a/Mage.Sets/src/mage/cards/t/TheCheeseStandsAlone.java b/Mage.Sets/src/mage/cards/t/TheCheeseStandsAlone.java index 51a15f4c2f..571754535a 100644 --- a/Mage.Sets/src/mage/cards/t/TheCheeseStandsAlone.java +++ b/Mage.Sets/src/mage/cards/t/TheCheeseStandsAlone.java @@ -1,7 +1,5 @@ - package mage.cards.t; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; @@ -18,8 +16,9 @@ import mage.game.Game; import mage.game.events.GameEvent; import mage.players.Player; +import java.util.UUID; + /** - * * @author spjspj */ public final class TheCheeseStandsAlone extends CardImpl { @@ -47,6 +46,7 @@ class CheeseStandsAloneContinuousEffect extends ContinuousRuleModifyingEffectImp private static final FilterControlledPermanent filter = new FilterControlledPermanent(); private boolean wonAlready = false; + static { filter.add(new NamePredicate("The Cheese Stands Alone")); } @@ -57,7 +57,7 @@ class CheeseStandsAloneContinuousEffect extends ContinuousRuleModifyingEffectImp } public CheeseStandsAloneContinuousEffect(final CheeseStandsAloneContinuousEffect effect) { - super(effect); + super(effect); } @Override @@ -72,7 +72,7 @@ class CheeseStandsAloneContinuousEffect extends ContinuousRuleModifyingEffectImp if (controller.getHand().isEmpty()) { int numberPerms = new PermanentsOnBattlefieldCount(new FilterControlledPermanent()).calculate(game, source, this); if (numberPerms == 1) { - if (game.getBattlefield().contains(filter, source.getControllerId(), 1, game)) { + if (game.getBattlefield().containsControlled(filter, source, game, 1)) { if (!wonAlready) { wonAlready = true; controller.won(game); diff --git a/Mage.Sets/src/mage/cards/t/TidalInfluence.java b/Mage.Sets/src/mage/cards/t/TidalInfluence.java index cdb1f64ed2..a25f2d06c0 100644 --- a/Mage.Sets/src/mage/cards/t/TidalInfluence.java +++ b/Mage.Sets/src/mage/cards/t/TidalInfluence.java @@ -1,7 +1,5 @@ - package mage.cards.t; -import java.util.UUID; import mage.ObjectColor; import mage.abilities.Ability; import mage.abilities.StateTriggeredAbility; @@ -31,8 +29,9 @@ import mage.filter.predicate.mageobject.NamePredicate; import mage.game.Game; import mage.game.events.GameEvent; +import java.util.UUID; + /** - * * @author LoneFox */ public final class TidalInfluence extends CardImpl { @@ -44,26 +43,26 @@ public final class TidalInfluence extends CardImpl { } public TidalInfluence(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}"); // Cast Tidal Influence only if no permanents named Tidal Influence are on the battlefield. this.getSpellAbility().addCost(new TidalInfluenceCost()); // Tidal Influence enters the battlefield with a tide counter on it. this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.TIDE.createInstance()), - "with a tide counter on it.")); + "with a tide counter on it.")); // At the beginning of your upkeep, put a tide counter on Tidal Influence. this.addAbility(new BeginningOfUpkeepTriggeredAbility(new AddCountersSourceEffect(CounterType.TIDE.createInstance()), - TargetController.YOU, false)); + TargetController.YOU, false)); // As long as there is exactly one tide counter on Tidal Influence, all blue creatures get -2/-0. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect( - new BoostAllEffect(-2, -0, Duration.WhileOnBattlefield, filter, false), - new SourceHasCounterCondition(CounterType.TIDE, 1, 1), - "As long as there is exactly one tide counter on {this}, all blue creatures get -2/-0."))); + new BoostAllEffect(-2, -0, Duration.WhileOnBattlefield, filter, false), + new SourceHasCounterCondition(CounterType.TIDE, 1, 1), + "As long as there is exactly one tide counter on {this}, all blue creatures get -2/-0."))); // As long as there are exactly three tide counters on Tidal Influence, all blue creatures get +2/+0. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect( - new BoostAllEffect(2, -0, Duration.WhileOnBattlefield, filter, false), - new SourceHasCounterCondition(CounterType.TIDE, 3, 3), - "As long as there are exactly three tide counter on {this}, all blue creatures get +2/-0."))); + new BoostAllEffect(2, -0, Duration.WhileOnBattlefield, filter, false), + new SourceHasCounterCondition(CounterType.TIDE, 3, 3), + "As long as there are exactly three tide counter on {this}, all blue creatures get +2/-0."))); // Whenever there are four tide counters on Tidal Influence, remove all tide counters from it. this.addAbility(new TidalInfluenceTriggeredAbility(new RemoveAllCountersSourceEffect(CounterType.TIDE))); } @@ -97,7 +96,7 @@ class TidalInfluenceCost extends CostImpl { @Override public boolean canPay(Ability ability, Ability source, UUID controllerId, Game game) { - return !game.getBattlefield().contains(filter, 1, game); + return !game.getBattlefield().contains(filter, source, game, 1); } @Override diff --git a/Mage.Sets/src/mage/cards/t/TravelersCloak.java b/Mage.Sets/src/mage/cards/t/TravelersCloak.java index 474de5cc44..c78c2a1471 100644 --- a/Mage.Sets/src/mage/cards/t/TravelersCloak.java +++ b/Mage.Sets/src/mage/cards/t/TravelersCloak.java @@ -1,13 +1,13 @@ - package mage.cards.t; -import java.util.UUID; +import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.ChooseCreatureTypeEffect; import mage.abilities.effects.common.ChooseLandTypeEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; @@ -15,24 +15,24 @@ import mage.abilities.keyword.EnchantAbility; import mage.abilities.keyword.LandwalkAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.AttachmentType; -import mage.constants.CardType; -import mage.constants.SubType; -import mage.constants.Outcome; -import mage.constants.Zone; +import mage.constants.*; import mage.filter.common.FilterLandPermanent; -import mage.filter.predicate.mageobject.ChosenSubtypePredicate; +import mage.filter.predicate.ObjectSourcePlayer; +import mage.filter.predicate.ObjectSourcePlayerPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author emerald000 */ public final class TravelersCloak extends CardImpl { public TravelersCloak(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}"); this.subtype.add(SubType.AURA); // Enchant creature @@ -41,18 +41,17 @@ public final class TravelersCloak extends CardImpl { this.getSpellAbility().addEffect(new AttachEffect(Outcome.AddAbility)); Ability ability = new EnchantAbility(auraTarget.getTargetName()); this.addAbility(ability); - + // As Traveler's Cloak enters the battlefield, choose a land type. this.addAbility(new AsEntersBattlefieldAbility(new ChooseLandTypeEffect(Outcome.AddAbility))); - + // When Traveler's Cloak enters the battlefield, draw a card. this.addAbility(new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1), false)); - + // Enchanted creature has landwalk of the chosen type. FilterLandPermanent filter = new FilterLandPermanent("Landwalk of the chosen type"); - filter.add(ChosenSubtypePredicate.instance); - Ability landwalkAbility = new LandwalkAbility(filter); - Effect effect = new GainAbilityAttachedEffect(landwalkAbility, AttachmentType.AURA); + filter.add(TravelersCloakChosenSubtypePredicate.instance); + Effect effect = new TravelersCloakGainAbilityAttachedEffect(filter); effect.setText("Enchanted creature has landwalk of the chosen type"); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect)); } @@ -66,3 +65,35 @@ public final class TravelersCloak extends CardImpl { return new TravelersCloak(this); } } + +class TravelersCloakGainAbilityAttachedEffect extends GainAbilityAttachedEffect { + + public TravelersCloakGainAbilityAttachedEffect(FilterLandPermanent filter) { + super(new LandwalkAbility(filter), AttachmentType.AURA); + } + + @Override + public void afterGain(Game game, Ability source, Permanent permanent, Ability addedAbility) { + super.afterGain(game, source, permanent, addedAbility); + + // ChooseLandTypeEffect keep settings in original source, but we must transfer it to real permanent + Object val = game.getState().getValue(source.getSourceId() + "_type"); + game.getState().setValue(permanent.getId() + "_landwalk_type", val); + } +} + +enum TravelersCloakChosenSubtypePredicate implements ObjectSourcePlayerPredicate> { + instance; + + @Override + public boolean apply(ObjectSourcePlayer input, Game game) { + SubType subType = ChooseCreatureTypeEffect.getChosenCreatureType(input.getSourceId(), game, "_landwalk_type"); + return input.getObject().hasSubtype(subType, game); + } + + @Override + public String toString() { + return "Chosen subtype"; + } +} + diff --git a/Mage.Sets/src/mage/cards/w/WeightOfConscience.java b/Mage.Sets/src/mage/cards/w/WeightOfConscience.java index 49f6d7c665..96a45851fd 100644 --- a/Mage.Sets/src/mage/cards/w/WeightOfConscience.java +++ b/Mage.Sets/src/mage/cards/w/WeightOfConscience.java @@ -1,9 +1,5 @@ package mage.cards.w; -import java.util.HashSet; -import java.util.Objects; -import java.util.Set; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleStaticAbility; @@ -25,8 +21,12 @@ import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; +import java.util.UUID; + /** - * * @author emerald000 */ public final class WeightOfConscience extends CardImpl { @@ -84,8 +84,8 @@ class WeightOfConscienceEffect extends OneShotEffect { // It was not blinked, use the standard method enchantment = game.getPermanentOrLKIBattlefield(source.getSourceId()); } - if (controller != null - && enchantment != null + if (controller != null + && enchantment != null && enchantment.getAttachedTo() != null) { Permanent creature = game.getPermanent(enchantment.getAttachedTo()); if (creature != null) { @@ -119,10 +119,10 @@ class WeightOfConscienceTarget extends TargetControlledCreaturePermanent { if (player != null) { // Choosing first target if (this.getTargets().isEmpty()) { - for (Permanent permanent : game.getBattlefield().getActivePermanents(filterUntapped, sourceControllerId, game)) { + for (Permanent permanent : game.getBattlefield().getActivePermanents(filterUntapped, sourceControllerId, sourceId, game)) { for (SubType subtype : permanent.getSubtype(game)) { if (subtype.getSubTypeSet() == SubTypeSet.CreatureType) { - if (game.getBattlefield().contains(new FilterControlledCreaturePermanent(subtype, subtype.toString()), sourceControllerId, game, 2)) { + if (game.getBattlefield().contains(new FilterControlledCreaturePermanent(subtype, subtype.toString()), sourceId, sourceControllerId, game, 2)) { possibleTargets.add(permanent.getId()); } } @@ -133,7 +133,7 @@ class WeightOfConscienceTarget extends TargetControlledCreaturePermanent { UUID firstTargetId = this.getTargets().get(0); Permanent firstTargetCreature = game.getPermanent(firstTargetId); if (firstTargetCreature != null) { - for (Permanent permanent : game.getBattlefield().getActivePermanents(filterUntapped, sourceControllerId, game)) { + for (Permanent permanent : game.getBattlefield().getActivePermanents(filterUntapped, sourceControllerId, sourceId, game)) { if (!permanent.getId().equals(firstTargetId) && firstTargetCreature.shareCreatureTypes(permanent, game)) { possibleTargets.add(permanent.getId()); } @@ -146,8 +146,8 @@ class WeightOfConscienceTarget extends TargetControlledCreaturePermanent { @Override public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) { - for (Permanent permanent1 : game.getBattlefield().getActivePermanents(filterUntapped, sourceControllerId, game)) { - for (Permanent permanent2 : game.getBattlefield().getActivePermanents(filterUntapped, sourceControllerId, game)) { + for (Permanent permanent1 : game.getBattlefield().getActivePermanents(filterUntapped, sourceControllerId, sourceId, game)) { + for (Permanent permanent2 : game.getBattlefield().getActivePermanents(filterUntapped, sourceControllerId, sourceId, game)) { if (!Objects.equals(permanent1, permanent2) && permanent1.shareCreatureTypes(permanent2, game)) { return true; } @@ -162,10 +162,10 @@ class WeightOfConscienceTarget extends TargetControlledCreaturePermanent { Permanent targetPermanent = game.getPermanent(id); if (targetPermanent != null) { if (this.getTargets().isEmpty()) { - for (Permanent permanent : game.getBattlefield().getActivePermanents(filterUntapped, source.getControllerId(), game)) { + for (Permanent permanent : game.getBattlefield().getActivePermanents(filterUntapped, source.getControllerId(), source.getSourceId(), game)) { for (SubType subtype : permanent.getSubtype(game)) { if (subtype.getSubTypeSet() == SubTypeSet.CreatureType) { - if (game.getBattlefield().contains(new FilterControlledCreaturePermanent(subtype, subtype.toString()), source.getControllerId(), game, 2)) { + if (game.getBattlefield().contains(new FilterControlledCreaturePermanent(subtype, subtype.toString()), source, game, 2)) { return true; } } @@ -173,9 +173,7 @@ class WeightOfConscienceTarget extends TargetControlledCreaturePermanent { } } else { Permanent firstTarget = game.getPermanent(this.getTargets().get(0)); - if (firstTarget != null && firstTarget.shareCreatureTypes(targetPermanent, game)) { - return true; - } + return firstTarget != null && firstTarget.shareCreatureTypes(targetPermanent, game); } } } diff --git a/Mage.Sets/src/mage/cards/w/Wirecat.java b/Mage.Sets/src/mage/cards/w/Wirecat.java index d7de3f3729..79bb613a15 100644 --- a/Mage.Sets/src/mage/cards/w/Wirecat.java +++ b/Mage.Sets/src/mage/cards/w/Wirecat.java @@ -69,7 +69,7 @@ public final class Wirecat extends CardImpl { @Override public boolean applies(Permanent permanent, Ability source, Game game) { if (permanent.getId().equals(source.getSourceId())) { - return game.getBattlefield().contains(StaticFilters.FILTER_ENCHANTMENT_PERMANENT, 1, game); + return game.getBattlefield().contains(StaticFilters.FILTER_ENCHANTMENT_PERMANENT, source, game, 1); } return false; } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/conditional/LegendarySorceryTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/conditional/LegendarySorceryTest.java index 68936f2290..aa70d08789 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/conditional/LegendarySorceryTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/conditional/LegendarySorceryTest.java @@ -1,4 +1,3 @@ - package org.mage.test.cards.conditional; import mage.constants.PhaseStep; @@ -7,7 +6,6 @@ import org.junit.Test; import org.mage.test.serverside.base.CardTestPlayerBase; /** - * * @author LevelX2 */ public class LegendarySorceryTest extends CardTestPlayerBase { @@ -55,10 +53,13 @@ public class LegendarySorceryTest extends CardTestPlayerBase { // Flying, first strike, vigilance, trample, haste, protection from black and from red addCard(Zone.BATTLEFIELD, playerB, "Akroma, Angel of Wrath", 1); // Legendary + // can't cast cause you don't have a legendary creature (only opponent have) castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Urza's Ruinous Blast"); + //setStrictChooseMode(true); setStopAt(1, PhaseStep.BEGIN_COMBAT); execute(); + //assertAllCommandsUsed(); assertGraveyardCount(playerA, "Urza's Ruinous Blast", 0); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/inv/TravelersCloakTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/inv/TravelersCloakTest.java new file mode 100644 index 0000000000..4e83fda10f --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/inv/TravelersCloakTest.java @@ -0,0 +1,54 @@ +package org.mage.test.cards.single.inv; + +import mage.abilities.keyword.LandwalkAbility; +import mage.constants.PhaseStep; +import mage.constants.Zone; +import mage.game.permanent.Permanent; +import org.junit.Assert; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * @author JayDi85 + */ + +public class TravelersCloakTest extends CardTestPlayerBase { + + @Test + public void test_MustHaveLandWalkOfTheChosenType() { + // Enchant creature + // As Traveler's Cloak enters the battlefield, choose a land type. + // When Traveler's Cloak enters the battlefield, draw a card. + // Enchanted creature has landwalk of the chosen type. + addCard(Zone.HAND, playerA, "Traveler's Cloak"); // {2}{U} + addCard(Zone.BATTLEFIELD, playerA, "Island", 3); + // + addCard(Zone.BATTLEFIELD, playerB, "Swamp", 1); + addCard(Zone.BATTLEFIELD, playerA, "Grizzly Bears", 1); + addCard(Zone.BATTLEFIELD, playerB, "Kitesail Corsair", 1); + + // cast and assign landwalk ability to creature + checkAbility("before", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Grizzly Bears", LandwalkAbility.class, false); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Traveler's Cloak", "Grizzly Bears"); + setChoice(playerA, "Swamp"); // land type for landwalk + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN); + checkAbility("after", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Grizzly Bears", LandwalkAbility.class, true); + + // check that it can't be blocked + attack(1, playerA, "Grizzly Bears"); + runCode("check blocking", 1, PhaseStep.DECLARE_BLOCKERS, playerB, (info, player, game) -> { + Permanent blocker = game.getBattlefield().getAllActivePermanents() + .stream() + .filter(p -> p.getName().equals("Kitesail Corsair")) + .findFirst() + .get(); + Assert.assertFalse("Grizzly Bears must be protected from blocking by Kitesail Corsair", + game.getCombat().getGroups().get(0).canBlock(blocker, game)); + }); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + assertAllCommandsUsed(); + } +} \ No newline at end of file diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/m21/ConspicuousSnoopTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/m21/ConspicuousSnoopTest.java index 140b141c3d..d9424400c9 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/single/m21/ConspicuousSnoopTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/m21/ConspicuousSnoopTest.java @@ -9,7 +9,7 @@ import org.mage.test.serverside.base.CardTestPlayerBase; public class ConspicuousSnoopTest extends CardTestPlayerBase { @Test - public void testTopCardLibraryRevealed(){ + public void test_TopCardLibraryRevealed() { // Play with the top card of your library revealed. addCard(Zone.BATTLEFIELD, playerA, "Conspicuous Snoop"); addCard(Zone.LIBRARY, playerA, "Swamp"); @@ -23,43 +23,49 @@ public class ConspicuousSnoopTest extends CardTestPlayerBase { } @Test - public void castGoblinSpellsFromLibrary(){ + public void test_castGoblinSpellsFromLibrary() { + skipInitShuffling(); + removeAllCardsFromLibrary(playerA); + // You may cast Goblin spells from the top of your library. addCard(Zone.BATTLEFIELD, playerA, "Conspicuous Snoop"); - - addCard(Zone.LIBRARY, playerA, "Goblin Lackey"); - skipInitShuffling(); - addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2); - // Whenever Goblin Lackey deals damage to a player, you may put a Goblin permanent card from your hand onto the battlefield. + addCard(Zone.LIBRARY, playerA, "Atog", 1); // second from top + addCard(Zone.LIBRARY, playerA, "Goblin Lackey", 1); // first from top + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2 * 2); + + // Whenever Goblin Lackey deals damage to a player, you may put a Goblin permanent card from your hand onto the battlefield. + checkPlayableAbility("can play goblin", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Goblin Lackey", true); + checkPlayableAbility("can't play non goblin before", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Atog", false); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Goblin Lackey"); + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN); + checkPlayableAbility("can't play non goblin after", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Atog", false); setStopAt(1, PhaseStep.PRECOMBAT_MAIN); setStrictChooseMode(true); execute(); assertAllCommandsUsed(); - assertPermanentCount(playerA, "Goblin Lackey", 1); + assertPermanentCount(playerA, "Goblin Lackey", 1); } @Test - public void hasActivatedAbilities(){ + public void test_hasActivatedAbilities() { addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1); // Play with the top card of your library revealed. // You may cast Goblin spells from the top of your library. // As long as the top card of your library is a Goblin card, Conspicuous Snoop has all activated abilities of that card. addCard(Zone.BATTLEFIELD, playerA, "Conspicuous Snoop"); // {R}: Goblin Balloon Brigade gains flying until end of turn. - addCard(Zone.LIBRARY, playerA, "Goblin Balloon Brigade"); + addCard(Zone.LIBRARY, playerA, "Goblin Balloon Brigade"); skipInitShuffling(); setStopAt(1, PhaseStep.PRECOMBAT_MAIN); - + setStrictChooseMode(true); execute(); - + assertAllCommandsUsed(); assertAbilityCount(playerA, "Conspicuous Snoop", ActivatedAbility.class, 3); // (2 X casts + gains flying ) - } } diff --git a/Mage/src/main/java/mage/abilities/common/LegendarySpellAbility.java b/Mage/src/main/java/mage/abilities/common/LegendarySpellAbility.java index 0cc00740fd..2ad18db7a9 100644 --- a/Mage/src/main/java/mage/abilities/common/LegendarySpellAbility.java +++ b/Mage/src/main/java/mage/abilities/common/LegendarySpellAbility.java @@ -2,11 +2,7 @@ package mage.abilities.common; import mage.abilities.Ability; import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Outcome; -import mage.constants.SuperType; -import mage.constants.Zone; +import mage.constants.*; import mage.filter.FilterPermanent; import mage.filter.predicate.Predicates; import mage.game.Game; @@ -65,7 +61,7 @@ class LegendarySpellAbilityCheckEffect extends ContinuousRuleModifyingEffectImpl @Override public boolean applies(GameEvent event, Ability source, Game game) { return event.getSourceId().equals(source.getSourceId()) - && !game.getBattlefield().contains(filter, event.getPlayerId(), 1, game); + && !game.getBattlefield().containsControlled(filter, source, game, 1); } @Override diff --git a/Mage/src/main/java/mage/abilities/condition/common/MetalcraftCondition.java b/Mage/src/main/java/mage/abilities/condition/common/MetalcraftCondition.java index 51e7683679..66cc9ce3bb 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/MetalcraftCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/MetalcraftCondition.java @@ -22,7 +22,7 @@ public enum MetalcraftCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - return game.getBattlefield().contains(filter, source.getControllerId(), 3, game); + return game.getBattlefield().containsControlled(filter, source, game, 3); } @Override diff --git a/Mage/src/main/java/mage/abilities/costs/common/ControlPermanentCost.java b/Mage/src/main/java/mage/abilities/costs/common/ControlPermanentCost.java index 17c366f5fc..c557d3b7d8 100644 --- a/Mage/src/main/java/mage/abilities/costs/common/ControlPermanentCost.java +++ b/Mage/src/main/java/mage/abilities/costs/common/ControlPermanentCost.java @@ -1,15 +1,15 @@ package mage.abilities.costs.common; import mage.abilities.Ability; +import mage.abilities.costs.Cost; import mage.abilities.costs.CostImpl; import mage.filter.common.FilterControlledPermanent; import mage.game.Game; import java.util.UUID; -import mage.abilities.costs.Cost; public class ControlPermanentCost extends CostImpl { - private FilterControlledPermanent filter; + private final FilterControlledPermanent filter; public ControlPermanentCost(FilterControlledPermanent filter) { this.filter = filter.copy(); @@ -23,7 +23,7 @@ public class ControlPermanentCost extends CostImpl { @Override public boolean canPay(Ability ability, Ability source, UUID controllerId, Game game) { - return game.getBattlefield().contains(filter, controllerId, 1, game); + return game.getBattlefield().containsControlled(filter, source.getSourceId(), controllerId, game, 1); } @Override diff --git a/Mage/src/main/java/mage/abilities/effects/common/ChooseCreatureTypeEffect.java b/Mage/src/main/java/mage/abilities/effects/common/ChooseCreatureTypeEffect.java index c1bdd3f9f4..1f89ff5a78 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/ChooseCreatureTypeEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/ChooseCreatureTypeEffect.java @@ -1,7 +1,5 @@ - package mage.abilities.effects.common; -import java.util.UUID; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; @@ -14,6 +12,8 @@ import mage.game.permanent.Permanent; import mage.players.Player; import mage.util.CardUtil; +import java.util.UUID; + /** * @author LevelX2 */ @@ -56,15 +56,19 @@ public class ChooseCreatureTypeEffect extends OneShotEffect { return new ChooseCreatureTypeEffect(this); } + public static SubType getChosenCreatureType(UUID objectId, Game game) { + return getChosenCreatureType(objectId, game, "_type"); + } + /** - * - * @param objectId sourceId the effect was exeuted under + * @param objectId sourceId the effect was exeuted under * @param game + * @param typePostfix special postfix if you want to store multiple choices from different effects * @return */ - public static SubType getChosenCreatureType(UUID objectId, Game game) { + public static SubType getChosenCreatureType(UUID objectId, Game game, String typePostfix) { SubType creatureType = null; - Object savedCreatureType = game.getState().getValue(objectId + "_type"); + Object savedCreatureType = game.getState().getValue(objectId + typePostfix); if (savedCreatureType != null) { creatureType = SubType.byDescription(savedCreatureType.toString()); } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAbilityAttachedEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAbilityAttachedEffect.java index 3eb23d9a7b..437d4a8b9d 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAbilityAttachedEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAbilityAttachedEffect.java @@ -96,10 +96,23 @@ public class GainAbilityAttachedEffect extends ContinuousEffectImpl { } if (permanent != null) { permanent.addAbility(ability, source.getSourceId(), game); + afterGain(game, source, permanent, ability); } return true; } + /** + * Calls after ability gain. Override it to apply additional data (example: transfer ability's settings from original to destination source) + * + * @param game + * @param source + * @param permanent + * @param addedAbility + */ + public void afterGain(Game game, Ability source, Permanent permanent, Ability addedAbility) { + // + } + private void setText() { StringBuilder sb = new StringBuilder(); sb.append(attachmentType.verb()); diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/PlayTheTopCardEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/PlayTheTopCardEffect.java index b0119f9485..34b136f26a 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/PlayTheTopCardEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/PlayTheTopCardEffect.java @@ -61,7 +61,7 @@ public class PlayTheTopCardEffect extends AsThoughEffectImpl { && playerId.equals(source.getControllerId()) && cardToCheck.isOwnedBy(source.getControllerId()) && (!cardToCheck.getManaCost().isEmpty() || cardToCheck.isLand()) - && filter.match(cardToCheck, game)) { + && filter.match(cardToCheck, source.getSourceId(), source.getControllerId(), game)) { Player player = game.getPlayer(cardToCheck.getOwnerId()); UUID needCardID = player.getLibrary().getFromTop(game) == null ? null : player.getLibrary().getFromTop(game).getId(); diff --git a/Mage/src/main/java/mage/abilities/effects/keyword/AmassEffect.java b/Mage/src/main/java/mage/abilities/effects/keyword/AmassEffect.java index f443ca65bc..fab9b36f96 100644 --- a/Mage/src/main/java/mage/abilities/effects/keyword/AmassEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/keyword/AmassEffect.java @@ -67,7 +67,7 @@ public class AmassEffect extends OneShotEffect { if (player == null) { return false; } - if (!game.getBattlefield().contains(filter, source.getControllerId(), 1, game)) { + if (!game.getBattlefield().containsControlled(filter, source, game, 1)) { new CreateTokenEffect(new ZombieArmyToken()).apply(game, source); } Target target = new TargetPermanent(filter); diff --git a/Mage/src/main/java/mage/abilities/keyword/ConvokeAbility.java b/Mage/src/main/java/mage/abilities/keyword/ConvokeAbility.java index 7af6c49a48..b5728d69b6 100644 --- a/Mage/src/main/java/mage/abilities/keyword/ConvokeAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/ConvokeAbility.java @@ -104,7 +104,7 @@ public class ConvokeAbility extends SimpleStaticAbility implements AlternateMana @Override public void addSpecialAction(Ability source, Game game, ManaCost unpaid) { Player controller = game.getPlayer(source.getControllerId()); - if (controller != null && game.getBattlefield().contains(filterUntapped, controller.getId(), 1, game)) { + if (controller != null && game.getBattlefield().containsControlled(filterUntapped, source, game, 1)) { if (source.getAbilityType() == AbilityType.SPELL) { SpecialAction specialAction = new ConvokeSpecialAction(unpaid, this); specialAction.setControllerId(source.getControllerId()); diff --git a/Mage/src/main/java/mage/abilities/keyword/LandwalkAbility.java b/Mage/src/main/java/mage/abilities/keyword/LandwalkAbility.java index dc4c59aee1..fad955ee02 100644 --- a/Mage/src/main/java/mage/abilities/keyword/LandwalkAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/LandwalkAbility.java @@ -14,6 +14,12 @@ import mage.game.permanent.Permanent; */ public class LandwalkAbility extends EvasionAbility { + /** + * Don't use source related filters here (example: landwalk for user selected land type). + * If you want it then use workaround from Traveler's Cloak to transfer settings after gain + * + * @param filter + */ public LandwalkAbility(FilterLandPermanent filter) { this(filter, true); } @@ -39,7 +45,6 @@ public class LandwalkAbility extends EvasionAbility { } return ruleText; } - } class LandwalkEffect extends RestrictionEffect { @@ -59,7 +64,7 @@ class LandwalkEffect extends RestrictionEffect { @Override public boolean canBeBlocked(Permanent attacker, Permanent blocker, Ability source, Game game, boolean canUseChooseDialogs) { - if (game.getBattlefield().contains(filter, blocker.getControllerId(), 1, game) + if (game.getBattlefield().contains(filter, source.getSourceId(), blocker.getControllerId(), game, 1) && null == game.getContinuousEffects().asThough(blocker.getId(), AsThoughEffectType.BLOCK_LANDWALK, source, blocker.getControllerId(), game)) { switch (filter.getMessage()) { case "plains": @@ -74,7 +79,6 @@ class LandwalkEffect extends RestrictionEffect { return null != game.getContinuousEffects().asThough(blocker.getId(), AsThoughEffectType.BLOCK_FORESTWALK, source, blocker.getControllerId(), game); default: return false; - } } return true; diff --git a/Mage/src/main/java/mage/filter/predicate/mageobject/ChosenSubtypePredicate.java b/Mage/src/main/java/mage/filter/predicate/mageobject/ChosenSubtypePredicate.java index bbde6c6b86..ab0deb49f2 100644 --- a/Mage/src/main/java/mage/filter/predicate/mageobject/ChosenSubtypePredicate.java +++ b/Mage/src/main/java/mage/filter/predicate/mageobject/ChosenSubtypePredicate.java @@ -1,4 +1,3 @@ - package mage.filter.predicate.mageobject; import mage.MageObject; @@ -9,6 +8,9 @@ import mage.filter.predicate.ObjectSourcePlayerPredicate; import mage.game.Game; /** + * Warning, chosen type assign to original source ability, but after gain you will see another sourceId, + * see Traveler's Cloak for workaround to trasfer settings + * * @author LoneFox */ public enum ChosenSubtypePredicate implements ObjectSourcePlayerPredicate> { diff --git a/Mage/src/main/java/mage/game/GameImpl.java b/Mage/src/main/java/mage/game/GameImpl.java index 122b55f330..d187a5ff4d 100644 --- a/Mage/src/main/java/mage/game/GameImpl.java +++ b/Mage/src/main/java/mage/game/GameImpl.java @@ -2276,7 +2276,7 @@ public abstract class GameImpl implements Game, Serializable { filterLegendName.add(SuperType.LEGENDARY.getPredicate()); filterLegendName.add(new NamePredicate(legend.getName())); filterLegendName.add(new ControllerIdPredicate(legend.getControllerId())); - if (getBattlefield().contains(filterLegendName, legend.getControllerId(), this, 2)) { + if (getBattlefield().contains(filterLegendName, null, legend.getControllerId(), this, 2)) { if (!replaceEvent(GameEvent.getEvent(GameEvent.EventType.DESTROY_PERMANENT_BY_LEGENDARY_RULE, legend.getId(), legend.getControllerId()))) { Player controller = this.getPlayer(legend.getControllerId()); if (controller != null) { diff --git a/Mage/src/main/java/mage/game/command/emblems/GideonOfTheTrialsEmblem.java b/Mage/src/main/java/mage/game/command/emblems/GideonOfTheTrialsEmblem.java index 700ba7591e..d426531082 100644 --- a/Mage/src/main/java/mage/game/command/emblems/GideonOfTheTrialsEmblem.java +++ b/Mage/src/main/java/mage/game/command/emblems/GideonOfTheTrialsEmblem.java @@ -50,7 +50,7 @@ class GideonOfTheTrialsCantLoseEffect extends ContinuousRuleModifyingEffectImpl public boolean applies(GameEvent event, Ability source, Game game) { if ((event.getType() == GameEvent.EventType.WINS && game.getOpponents(source.getControllerId()).contains(event.getPlayerId())) || (event.getType() == GameEvent.EventType.LOSES && event.getPlayerId().equals(source.getControllerId()))) { - return game.getBattlefield().contains(filter, source.getControllerId(), 1, game); + return game.getBattlefield().containsControlled(filter, source, game, 1); } return false; } diff --git a/Mage/src/main/java/mage/game/permanent/Battlefield.java b/Mage/src/main/java/mage/game/permanent/Battlefield.java index 054dfcbd4f..24c53796f4 100644 --- a/Mage/src/main/java/mage/game/permanent/Battlefield.java +++ b/Mage/src/main/java/mage/game/permanent/Battlefield.java @@ -1,5 +1,6 @@ package mage.game.permanent; +import mage.abilities.Ability; import mage.abilities.keyword.PhasingAbility; import mage.constants.CardType; import mage.constants.RangeOfInfluence; @@ -92,21 +93,8 @@ public class Battlefield implements Serializable { } } - /** - * Returns true if the battlefield contains at least 1 {@link Permanent} - * that matches the filter. This method ignores the range of influence. - * - * @param filter - * @param num - * @param game - * @return boolean - */ - public boolean contains(FilterPermanent filter, int num, Game game) { - return field.values() - .stream() - .filter(permanent -> filter.match(permanent, game) - && permanent.isPhasedIn()).count() >= num; - + public boolean containsControlled(FilterPermanent filter, Ability source, Game game, int num) { + return containsControlled(filter, source.getSourceId(), source.getControllerId(), game, num); } /** @@ -115,43 +103,49 @@ public class Battlefield implements Serializable { * ignores the range of influence. * * @param filter - * @param controllerId + * @param sourceId + * @param controllerId controller and source can be different (from different players) * @param num * @param game * @return boolean */ - public boolean contains(FilterPermanent filter, UUID controllerId, int num, Game game) { + public boolean containsControlled(FilterPermanent filter, UUID sourceId, UUID controllerId, Game game, int num) { return field.values() .stream() .filter(permanent -> permanent.isControlledBy(controllerId) - && filter.match(permanent, game) + && filter.match(permanent, sourceId, controllerId, game) && permanent.isPhasedIn()) .count() >= num; } + public boolean contains(FilterPermanent filter, Ability source, Game game, int num) { + return contains(filter, source.getSourceId(), source.getControllerId(), game, num); + } + /** * Returns true if the battlefield contains num or more {@link Permanent} * that is within the range of influence of the specified player id and that * matches the supplied filter. * * @param filter + * @param sourceId can be null for default SBA checks like legendary rule * @param sourcePlayerId * @param game * @param num * @return boolean */ - public boolean contains(FilterPermanent filter, UUID sourcePlayerId, Game game, int num) { + public boolean contains(FilterPermanent filter, UUID sourceId, UUID sourcePlayerId, Game game, int num) { if (game.getRangeOfInfluence() == RangeOfInfluence.ALL) { return field.values().stream() - .filter(permanent -> filter.match(permanent, null, sourcePlayerId, game) + .filter(permanent -> filter.match(permanent, sourceId, sourcePlayerId, game) && permanent.isPhasedIn()).count() >= num; } else { List range = game.getState().getPlayersInRange(sourcePlayerId, game); return field.values().stream() .filter(permanent -> range.contains(permanent.getControllerId()) - && filter.match(permanent, null, sourcePlayerId, game) + && filter.match(permanent, sourceId, sourcePlayerId, game) && permanent.isPhasedIn()) .count() >= num; }