mirror of
https://github.com/correl/mage.git
synced 2024-12-24 11:50:45 +00:00
Improved some source related filters in effects:
* Fixed that some cards ignore range of influence or source related filters; * Improved ChosenSubtypePredicate to work with gain abilities;
This commit is contained in:
parent
fdcf2c616b
commit
a307e5934f
32 changed files with 291 additions and 197 deletions
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 (<i>If two or more permanents are tied for lowest cost, target any one of them.</i>)"
|
||||
"nonland permanent with the lowest converted mana cost (<i>If two or more permanents are tied for lowest cost, target any one of them.</i>)"
|
||||
);
|
||||
|
||||
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<Permanent> {
|
||||
|
||||
class HasLowestCMCAmongstNonlandPermanentsPredicate implements ObjectSourcePlayerPredicate<ObjectSourcePlayer<Permanent>> {
|
||||
|
||||
@Override
|
||||
public boolean apply(Permanent input, Game game) {
|
||||
public boolean apply(ObjectSourcePlayer<Permanent> 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);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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)) {
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<ObjectSourcePlayer<MageObject>> {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public boolean apply(ObjectSourcePlayer<MageObject> 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";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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 )
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<ObjectSourcePlayer<MageObject>> {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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<UUID> 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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue