This commit is contained in:
jeffwadsworth 2020-02-06 17:47:08 -06:00
parent b75a5d86b1
commit d6c2f031d0
28 changed files with 813 additions and 650 deletions

View file

@ -4,11 +4,7 @@ import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.abilities.mana.BlackManaAbility;
import mage.abilities.mana.BlueManaAbility;
import mage.abilities.mana.GreenManaAbility;
import mage.abilities.mana.RedManaAbility;
import mage.abilities.mana.WhiteManaAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
@ -38,73 +34,56 @@ public final class BloodMoon extends CardImpl {
public BloodMoon copy() {
return new BloodMoon(this);
}
}
class BloodMoonEffect extends ContinuousEffectImpl {
static class BloodMoonEffect extends ContinuousEffectImpl {
private static final FilterLandPermanent filter = new FilterLandPermanent();
private static final FilterLandPermanent filter = new FilterLandPermanent();
static {
filter.add(Predicates.not(SuperType.BASIC.getPredicate()));
}
BloodMoonEffect() {
super(Duration.WhileOnBattlefield, Outcome.Detriment);
this.staticText = "Nonbasic lands are Mountains";
}
BloodMoonEffect(final BloodMoonEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
return false;
}
@Override
public BloodMoonEffect copy() {
return new BloodMoonEffect(this);
}
@Override
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
for (Permanent land : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), game)) {
switch (layer) {
case TypeChangingEffects_4:
// 305.7 Note that this doesn't remove any abilities that were granted to the land by other effects
// So the ability removing has to be done before Layer 6
//land.getSubtype(game).removeAll(SubType.getLandTypes(false));
land.getSubtype(game).clear();
land.getSubtype(game).add(SubType.MOUNTAIN);
land.removeAllAbilities(source.getSourceId(), game);
break;
case AbilityAddingRemovingEffects_6:
land.removeAllAbilities(source.getSourceId(), game);
if (land.getSubtype(game).contains(SubType.FOREST)) {
land.addAbility(new GreenManaAbility(), source.getSourceId(), game);
}
if (land.getSubtype(game).contains(SubType.PLAINS)) {
land.addAbility(new WhiteManaAbility(), source.getSourceId(), game);
}
if (land.getSubtype(game).contains(SubType.MOUNTAIN)) {
land.addAbility(new RedManaAbility(), source.getSourceId(), game);
}
if (land.getSubtype(game).contains(SubType.ISLAND)) {
land.addAbility(new BlueManaAbility(), source.getSourceId(), game);
}
if (land.getSubtype(game).contains(SubType.SWAMP)) {
land.addAbility(new BlackManaAbility(), source.getSourceId(), game);
}
break;
}
static {
filter.add(Predicates.not(SuperType.BASIC.getPredicate()));
}
return true;
}
@Override
public boolean hasLayer(Layer layer) {
return layer == Layer.AbilityAddingRemovingEffects_6
|| layer == Layer.TypeChangingEffects_4;
BloodMoonEffect() {
super(Duration.WhileOnBattlefield, Outcome.Detriment);
this.staticText = "Nonbasic lands are Mountains";
this.dependencyTypes.add(DependencyType.BecomeMountain);
}
BloodMoonEffect(final BloodMoonEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
return false;
}
@Override
public BloodMoonEffect copy() {
return new BloodMoonEffect(this);
}
@Override
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
for (Permanent land : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), game)) {
switch (layer) {
case TypeChangingEffects_4:
// 305.7 Note that this doesn't remove any abilities that were granted to the land by other effects
// So the ability removing has to be done before Layer 6
// Lands have their mana ability intrinsically, so that is added in layer 4
land.getSubtype(game).removeAll(SubType.getLandTypes());
land.getSubtype(game).add(SubType.MOUNTAIN);
land.removeAllAbilities(source.getSourceId(), game);
land.addAbility(new RedManaAbility(), source.getSourceId(), game);
break;
}
}
return true;
}
@Override
public boolean hasLayer(Layer layer) {
return layer == Layer.TypeChangingEffects_4;
}
}
}

View file

@ -26,12 +26,16 @@ public final class Cloudform extends CardImpl {
public Cloudform(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{U}{U}");
// When Cloudform enters the battlefield, it becomes an Aura with enchant creature. Manifest the top card of your library and attach Cloudform to it.
// When Cloudform enters the battlefield, it becomes an Aura with enchant creature.
// Manifest the top card of your library and attach Cloudform to it.
this.addAbility(new EntersBattlefieldTriggeredAbility(new BecomesAuraAttachToManifestSourceEffect()));
// Enchanted creature has flying and hexproof.
Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(FlyingAbility.getInstance(), AttachmentType.AURA, Duration.WhileOnBattlefield));
Effect effect = new GainAbilityAttachedEffect(HexproofAbility.getInstance(), AttachmentType.AURA, Duration.WhileOnBattlefield);
Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD,
new GainAbilityAttachedEffect(FlyingAbility.getInstance(),
AttachmentType.AURA, Duration.WhileOnBattlefield));
Effect effect = new GainAbilityAttachedEffect(
HexproofAbility.getInstance(), AttachmentType.AURA, Duration.WhileOnBattlefield);
effect.setText("and hexproof");
ability.addEffect(effect);
this.addAbility(ability);

View file

@ -17,13 +17,16 @@ import mage.game.stack.Spell;
import mage.game.stack.StackObject;
import mage.players.Player;
import mage.util.SubTypeList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.Effect;
/**
* @author anonymous
* @author bunchOfDevs
*/
public final class Conspiracy extends CardImpl {
@ -32,8 +35,11 @@ public final class Conspiracy extends CardImpl {
// As Conspiracy enters the battlefield, choose a creature type.
this.addAbility(new AsEntersBattlefieldAbility(new ChooseCreatureTypeEffect(Outcome.Neutral)));
// Creature cards you own that aren't on the battlefield, creature spells you control, and creatures you control are the chosen type.
// Creature cards you own that aren't on the battlefield, creature
// spells you control, and creatures you control are the chosen type.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConspiracyEffect()));
}
public Conspiracy(final Conspiracy card) {
@ -44,113 +50,129 @@ public final class Conspiracy extends CardImpl {
public Conspiracy copy() {
return new Conspiracy(this);
}
}
class ConspiracyEffect extends ContinuousEffectImpl {
static class ConspiracyEffect extends ContinuousEffectImpl {
public ConspiracyEffect() {
super(Duration.WhileOnBattlefield, Outcome.Neutral);
staticText = "Creatures you control are the chosen type. The same is true for creature spells you control and creature cards you own that aren't on the battlefield.";
}
public ConspiracyEffect() {
super(Duration.WhileOnBattlefield, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Neutral);
staticText = "Creatures you control are the chosen type. The same is "
+ "true for creature spells you control and creature cards "
+ "you own that aren't on the battlefield.";
}
public ConspiracyEffect(final ConspiracyEffect effect) {
super(effect);
}
public ConspiracyEffect(final ConspiracyEffect effect) {
super(effect);
}
@Override
public ConspiracyEffect copy() {
return new ConspiracyEffect(this);
}
@Override
public ConspiracyEffect copy() {
return new ConspiracyEffect(this);
}
@Override
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
Player controller = game.getPlayer(source.getControllerId());
SubType subType = ChooseCreatureTypeEffect.getChosenCreatureType(source.getSourceId(), game);
if (controller != null && subType != null) {
// Creature cards you own that aren't on the battlefield
// in graveyard
for (UUID cardId : controller.getGraveyard()) {
Card card = game.getCard(cardId);
if (card != null && card.isCreature()) {
setCreatureSubtype(card, subType, game);
}
}
// on Hand
for (UUID cardId : controller.getHand()) {
Card card = game.getCard(cardId);
if (card != null && card.isCreature()) {
setCreatureSubtype(card, subType, game);
}
}
// in Exile
for (Card card : game.getState().getExile().getAllCards(game)) {
if (card.isOwnedBy(controller.getId()) && card.isCreature()) {
setCreatureSubtype(card, subType, game);
}
}
// in Library (e.g. for Mystical Teachings)
for (Card card : controller.getLibrary().getCards(game)) {
if (card.isOwnedBy(controller.getId()) && card.isCreature()) {
setCreatureSubtype(card, subType, game);
}
}
// commander in command zone
for (UUID commanderId : game.getCommandersIds(controller)) {
if (game.getState().getZone(commanderId) == Zone.COMMAND) {
Card card = game.getCard(commanderId);
if (card != null && card.isCreature()) {
setCreatureSubtype(card, subType, game);
@Override
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
Player controller = game.getPlayer(source.getControllerId());
SubType subType = ChooseCreatureTypeEffect.getChosenCreatureType(source.getSourceId(), game);
switch (layer) {
case TypeChangingEffects_4:
if (controller != null && subType != null) {
// Creature cards you own that aren't on the battlefield
// in graveyard
for (UUID cardId : controller.getGraveyard()) {
Card card = game.getCard(cardId);
if (card != null && card.isCreature()) {
setCreatureSubtype(card, subType, game);
}
}
// on Hand
for (UUID cardId : controller.getHand()) {
Card card = game.getCard(cardId);
if (card != null && card.isCreature()) {
setCreatureSubtype(card, subType, game);
}
}
// in Exile
for (Card card : game.getState().getExile().getAllCards(game)) {
if (card.isOwnedBy(controller.getId()) && card.isCreature()) {
setCreatureSubtype(card, subType, game);
}
}
// in Library (e.g. for Mystical Teachings)
for (Card card : controller.getLibrary().getCards(game)) {
if (card.isOwnedBy(controller.getId()) && card.isCreature()) {
setCreatureSubtype(card, subType, game);
}
}
// commander in command zone
for (UUID commanderId : game.getCommandersIds(controller)) {
if (game.getState().getZone(commanderId) == Zone.COMMAND) {
Card card = game.getCard(commanderId);
if (card != null && card.isCreature()) {
setCreatureSubtype(card, subType, game);
}
}
}
// creature spells you control
for (Iterator<StackObject> iterator = game.getStack().iterator(); iterator.hasNext();) {
StackObject stackObject = iterator.next();
if (stackObject instanceof Spell
&& stackObject.isControlledBy(source.getControllerId())
&& stackObject.isCreature()) {
Card card = ((Spell) stackObject).getCard();
setCreatureSubtype(card, subType, game);
}
}
// creatures you control
List<Permanent> creatures = game.getState().getBattlefield().getAllActivePermanents(
new FilterControlledCreaturePermanent(), source.getControllerId(), game);
for (Permanent creature : creatures) {
setCreatureSubtype(creature, subType, game);
}
}
return true;
}
return false;
}
private void setCreatureSubtype(MageObject object, SubType subtype, Game game) {
if (object != null) {
if (object instanceof Card) {
Card card = (Card) object;
setChosenSubtype(
game.getState().getCreateCardAttribute(card, game).getSubtype(),
subtype);
} else {
setChosenSubtype(object.getSubtype(game), subtype);
}
}
// creature spells you control
for (Iterator<StackObject> iterator = game.getStack().iterator(); iterator.hasNext(); ) {
StackObject stackObject = iterator.next();
if (stackObject instanceof Spell
&& stackObject.isControlledBy(source.getControllerId())
&& stackObject.isCreature()) {
Card card = ((Spell) stackObject).getCard();
setCreatureSubtype(card, subType, game);
}
}
// creatures you control
List<Permanent> creatures = game.getBattlefield().getAllActivePermanents(
new FilterControlledCreaturePermanent(), source.getControllerId(), game);
for (Permanent creature : creatures) {
setCreatureSubtype(creature, subType, game);
}
return true;
}
return false;
}
private void setCreatureSubtype(MageObject object, SubType subtype, Game game) {
if (object != null) {
if (object instanceof Card) {
Card card = (Card) object;
setChosenSubtype(
game.getState().getCreateCardAttribute(card, game).getSubtype(),
subtype);
} else {
setChosenSubtype(object.getSubtype(game), subtype);
private void setChosenSubtype(SubTypeList subtype, SubType choice) {
if (subtype.size() != 1 || !subtype.contains(choice)) {
subtype.clear();
subtype.add(choice);
}
}
}
private void setChosenSubtype(SubTypeList subtype, SubType choice) {
if (subtype.size() != 1 || !subtype.contains(choice)) {
subtype.clear();
subtype.add(choice);
@Override
public boolean apply(Game game, Ability source) {
return false;
}
}
@Override
public boolean apply(Game game, Ability source) {
return false;
}
@Override
public boolean hasLayer(Layer layer) {
return layer == Layer.TypeChangingEffects_4;
}
@Override
public boolean hasLayer(Layer layer) {
return layer == Layer.TypeChangingEffects_4;
@Override
public Set<UUID> isDependentTo(List<ContinuousEffect> allEffectsInLayer) {
// the dependent classes needs to be an enclosed class for dependent check of continuous effects
return allEffectsInLayer.stream()
.filter(effect
-> mage.cards.s.StarfieldOfNyx.class.equals(effect.getClass().getEnclosingClass())
|| mage.cards.o.Opalescence.class.equals(effect.getClass().getEnclosingClass()))
.map(Effect::getId)
.collect(Collectors.toSet());
}
}
}

View file

@ -12,10 +12,6 @@ import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.SacrificeSourceUnlessPaysEffect;
import mage.abilities.mana.BlackManaAbility;
import mage.abilities.mana.BlueManaAbility;
import mage.abilities.mana.GreenManaAbility;
import mage.abilities.mana.RedManaAbility;
import mage.abilities.mana.WhiteManaAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@ -80,42 +76,12 @@ public final class Conversion extends CardImpl {
switch (layer) {
case TypeChangingEffects_4:
if (land.getSubtype(game).contains(SubType.MOUNTAIN)) {
land.getSubtype(game).clear();
land.getSubtype(game).removeAll(SubType.getLandTypes());
land.getSubtype(game).add(SubType.PLAINS);
game.getState().setValue("conversion"
+ source.getId()
+ land.getId()
+ land.getZoneChangeCounter(game),
"true");
}
break;
case AbilityAddingRemovingEffects_6:
if (game.getState().getValue("conversion"
+ source.getId()
+ land.getId()
+ land.getZoneChangeCounter(game)) != null
&& game.getState().getValue("conversion"
+ source.getId()
+ land.getId()
+ land.getZoneChangeCounter(game)).equals("true")) {
land.removeAllAbilities(source.getSourceId(), game);
if (land.getSubtype(game).contains(SubType.FOREST)) {
land.addAbility(new GreenManaAbility(), source.getSourceId(), game);
}
if (land.getSubtype(game).contains(SubType.PLAINS)) {
land.addAbility(new WhiteManaAbility(), source.getSourceId(), game);
}
if (land.getSubtype(game).contains(SubType.MOUNTAIN)) {
land.addAbility(new RedManaAbility(), source.getSourceId(), game);
}
if (land.getSubtype(game).contains(SubType.ISLAND)) {
land.addAbility(new BlueManaAbility(), source.getSourceId(), game);
}
if (land.getSubtype(game).contains(SubType.SWAMP)) {
land.addAbility(new BlackManaAbility(), source.getSourceId(), game);
}
land.addAbility(new WhiteManaAbility(), source.getSourceId(), game);
break;
}
break;
}
}
return true;
@ -123,15 +89,14 @@ public final class Conversion extends CardImpl {
@Override
public boolean hasLayer(Layer layer) {
return layer == Layer.AbilityAddingRemovingEffects_6
|| layer == Layer.TypeChangingEffects_4;
return layer == Layer.TypeChangingEffects_4;
}
@Override
public Set<UUID> isDependentTo(List<ContinuousEffect> allEffectsInLayer) {
return allEffectsInLayer
.stream()
.filter(effect -> effect.getDependencyTypes().contains(DependencyType.BecomePlains))
.filter(effect -> effect.getDependencyTypes().contains(DependencyType.BecomeMountain))
.map(Effect::getId)
.collect(Collectors.toSet());
}

View file

@ -39,7 +39,7 @@ public final class EnchantedEvening extends CardImpl {
}
// need to be enclosed class for dependent check of continuous effects
class EnchangedEveningEffect extends ContinuousEffectImpl {
static class EnchangedEveningEffect extends ContinuousEffectImpl {
private final CardType addedCardType;
private final FilterPermanent filter;
@ -48,7 +48,8 @@ public final class EnchantedEvening extends CardImpl {
super(duration, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Benefit);
this.addedCardType = addedCardType;
this.filter = filter;
dependencyTypes.add(DependencyType.EnchantmentAddingRemoving);
this.dependencyTypes.add(DependencyType.EnchantmentAddingRemoving);
this.dependencyTypes.add(DependencyType.AuraAddingRemoving);
}
public EnchangedEveningEffect(final EnchangedEveningEffect effect) {

View file

@ -38,9 +38,8 @@ public final class Frogify extends CardImpl {
Effect effect = new BecomesCreatureAttachedEffect(
new CreatureToken(1, 1, "", SubType.FROG).withColor("U"),
"Enchanted creature loses all abilities and is a blue Frog creature with base power and toughness 1/1",
Duration.WhileOnBattlefield, BecomesCreatureAttachedEffect.LoseType.ALL
Duration.WhileOnBattlefield, BecomesCreatureAttachedEffect.LoseType.ALL, Outcome.Detriment
);
effect.setOutcome(Outcome.Detriment);
this.addAbility(new SimpleStaticAbility(effect));
}

View file

@ -18,10 +18,6 @@ import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
import mage.abilities.mana.BlackManaAbility;
import mage.abilities.mana.BlueManaAbility;
import mage.abilities.mana.GreenManaAbility;
import mage.abilities.mana.RedManaAbility;
/**
*
@ -33,7 +29,8 @@ public final class Glaciers extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}{U}");
// At the beginning of your upkeep, sacrifice Glaciers unless you pay {W}{U}.
this.addAbility(new BeginningOfUpkeepTriggeredAbility(new SacrificeSourceUnlessPaysEffect(new ManaCostsImpl("{W}{U}")), TargetController.YOU, false));
this.addAbility(new BeginningOfUpkeepTriggeredAbility(
new SacrificeSourceUnlessPaysEffect(new ManaCostsImpl("{W}{U}")), TargetController.YOU, false));
// All Mountains are Plains.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GlaciersEffect()));
@ -74,58 +71,30 @@ public final class Glaciers extends CardImpl {
for (Permanent land : game.getBattlefield().getAllActivePermanents(CardType.LAND)) {
switch (layer) {
case TypeChangingEffects_4:
// the land mana ability is intrinsic, so apply at this layer not layer 6
if (land.getSubtype(game).contains(SubType.MOUNTAIN)) {
land.getSubtype(game).clear();
land.getSubtype(game).removeAll(SubType.getLandTypes());
land.getSubtype(game).add(SubType.PLAINS);
game.getState().setValue("glaciers"
+ source.getId()
+ land.getId()
+ land.getZoneChangeCounter(game), "true");
}
break;
case AbilityAddingRemovingEffects_6:
if (game.getState().getValue("glaciers"
+ source.getId()
+ land.getId()
+ land.getZoneChangeCounter(game)) != null
&& game.getState().getValue("glaciers"
+ source.getId()
+ land.getId()
+ land.getZoneChangeCounter(game)).equals("true")) {
land.removeAllAbilities(source.getSourceId(), game);
if (land.getSubtype(game).contains(SubType.FOREST)) {
land.addAbility(new GreenManaAbility(), source.getSourceId(), game);
}
if (land.getSubtype(game).contains(SubType.PLAINS)) {
land.addAbility(new WhiteManaAbility(), source.getSourceId(), game);
}
if (land.getSubtype(game).contains(SubType.MOUNTAIN)) {
land.addAbility(new RedManaAbility(), source.getSourceId(), game);
}
if (land.getSubtype(game).contains(SubType.ISLAND)) {
land.addAbility(new BlueManaAbility(), source.getSourceId(), game);
}
if (land.getSubtype(game).contains(SubType.SWAMP)) {
land.addAbility(new BlackManaAbility(), source.getSourceId(), game);
}
land.addAbility(new WhiteManaAbility(), source.getSourceId(), game);
break;
}
break;
}
}
return true;
}
@Override
public boolean hasLayer(Layer layer) {
return layer == Layer.AbilityAddingRemovingEffects_6
|| layer == Layer.TypeChangingEffects_4;
return layer == Layer.TypeChangingEffects_4;
}
@Override
public Set<UUID> isDependentTo(List<ContinuousEffect> allEffectsInLayer) {
return allEffectsInLayer
.stream()
.filter(effect -> effect.getDependencyTypes().contains(DependencyType.BecomePlains))
.filter(effect -> effect.getDependencyTypes().contains(DependencyType.BecomeMountain))
.map(Effect::getId)
.collect(Collectors.toSet());
}

View file

@ -1,4 +1,3 @@
package mage.cards.h;
import java.util.UUID;
@ -13,7 +12,7 @@ import mage.constants.Layer;
import mage.constants.Outcome;
import mage.constants.SubLayer;
import mage.constants.Zone;
import mage.filter.StaticFilters;
import mage.filter.common.FilterCreaturePermanent;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
@ -28,7 +27,8 @@ public final class Humility extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}{W}");
// All creatures lose all abilities and have base power and toughness 1/1.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new HumilityEffect(Duration.WhileOnBattlefield)));
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
new HumilityEffect(Duration.WhileOnBattlefield)));
}
@ -40,53 +40,55 @@ public final class Humility extends CardImpl {
public Humility copy() {
return new Humility(this);
}
}
class HumilityEffect extends ContinuousEffectImpl {
static class HumilityEffect extends ContinuousEffectImpl {
public HumilityEffect(Duration duration) {
super(duration, Outcome.LoseAbility);
staticText = "All creatures lose all abilities and have base power and toughness 1/1";
}
public HumilityEffect(final HumilityEffect effect) {
super(effect);
}
@Override
public HumilityEffect copy() {
return new HumilityEffect(this);
}
@Override
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
Player player = game.getPlayer(source.getControllerId());
if (player != null) {
for (Permanent permanent : game.getState().getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, player.getId(), source.getSourceId(), game)) {
switch (layer) {
case AbilityAddingRemovingEffects_6:
permanent.removeAllAbilities(source.getSourceId(), game);
break;
case PTChangingEffects_7:
if (sublayer == SubLayer.SetPT_7b) {
permanent.getPower().setValue(1);
permanent.getToughness().setValue(1);
}
}
}
return true;
public HumilityEffect(Duration duration) {
super(duration, Outcome.LoseAbility);
staticText = "All creatures lose all abilities and have base power and toughness 1/1";
}
return false;
}
@Override
public boolean apply(Game game, Ability source) {
return false;
}
public HumilityEffect(final HumilityEffect effect) {
super(effect);
}
@Override
public boolean hasLayer(Layer layer) {
return layer == Layer.AbilityAddingRemovingEffects_6 || layer == Layer.PTChangingEffects_7;
}
@Override
public HumilityEffect copy() {
return new HumilityEffect(this);
}
@Override
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
Player player = game.getPlayer(source.getControllerId());
if (player != null) {
for (Permanent permanent : game.getBattlefield().getActivePermanents(
new FilterCreaturePermanent(), source.getControllerId(), source.getSourceId(), game)) {
switch (layer) {
case AbilityAddingRemovingEffects_6:
permanent.removeAllAbilities(source.getSourceId(), game);
break;
case PTChangingEffects_7:
if (sublayer == SubLayer.SetPT_7b) {
permanent.getPower().setValue(1);
permanent.getToughness().setValue(1);
}
}
}
return true;
}
return false;
}
@Override
public boolean apply(Game game, Ability source) {
return false;
}
@Override
public boolean hasLayer(Layer layer) {
return layer == Layer.AbilityAddingRemovingEffects_6
|| layer == Layer.PTChangingEffects_7;
}
}
}

View file

@ -20,9 +20,9 @@ import mage.cards.CardSetInfo;
import mage.choices.ChoiceBasicLandType;
import mage.choices.ChoiceImpl;
import mage.constants.CardType;
import mage.constants.DependencyType;
import mage.constants.Duration;
import mage.constants.Layer;
import static mage.constants.Layer.AbilityAddingRemovingEffects_6;
import static mage.constants.Layer.TypeChangingEffects_4;
import mage.constants.Outcome;
import mage.constants.SubLayer;
@ -92,43 +92,33 @@ class IllusionaryTerrainEffect extends ContinuousEffectImpl {
if (land.isBasic()) {
switch (layer) {
case TypeChangingEffects_4:
// the land mana ability is intrinsic, so add it here, not layer 6
if (land.getSubtype(game).contains(firstChoice)) {
land.getSubtype(game).clear();
land.getSubtype(game).removeAll(SubType.getLandTypes());
land.getSubtype(game).add(secondChoice);
game.getState().setValue("illusionaryTerrain"
+ source.getId()
+ land.getId()
+ land.getZoneChangeCounter(game),
"true");
}
break;
case AbilityAddingRemovingEffects_6:
if (game.getState().getValue("illusionaryTerrain"
+ source.getId()
+ land.getId()
+ land.getZoneChangeCounter(game)) != null
&& game.getState().getValue("illusionaryTerrain"
+ source.getId()
+ land.getId()
+ land.getZoneChangeCounter(game)).equals("true")) {
land.removeAllAbilities(source.getSourceId(), game);
if (land.getSubtype(game).contains(SubType.FOREST)) {
this.dependencyTypes.add(DependencyType.BecomeForest);
land.addAbility(new GreenManaAbility(), source.getSourceId(), game);
}
if (land.getSubtype(game).contains(SubType.PLAINS)) {
this.dependencyTypes.add(DependencyType.BecomePlains);
land.addAbility(new WhiteManaAbility(), source.getSourceId(), game);
}
if (land.getSubtype(game).contains(SubType.MOUNTAIN)) {
this.dependencyTypes.add(DependencyType.BecomeMountain);
land.addAbility(new RedManaAbility(), source.getSourceId(), game);
}
if (land.getSubtype(game).contains(SubType.ISLAND)) {
this.dependencyTypes.add(DependencyType.BecomeIsland);
land.addAbility(new BlueManaAbility(), source.getSourceId(), game);
}
if (land.getSubtype(game).contains(SubType.SWAMP)) {
this.dependencyTypes.add(DependencyType.BecomeSwamp);
land.addAbility(new BlackManaAbility(), source.getSourceId(), game);
}
break;
}
break;
}
}
}
@ -144,9 +134,7 @@ class IllusionaryTerrainEffect extends ContinuousEffectImpl {
@Override
public boolean hasLayer(Layer layer) {
return layer == Layer.TypeChangingEffects_4
|| layer == Layer.AbilityAddingRemovingEffects_6;
return layer == Layer.TypeChangingEffects_4;
}
}
@ -180,19 +168,26 @@ class ChooseTwoBasicLandTypesEffect extends OneShotEffect {
&& mageObject != null) {
ChoiceImpl choices = new ChoiceBasicLandType();
if (controller.choose(Outcome.Neutral, choices, game)) {
game.informPlayers(mageObject.getName() + ": First chosen basic land type is " + choices.getChoice());
game.getState().setValue(mageObject.getId().toString() + "firstChoice", choices.getChoice());
choiceOne = SubType.byDescription((String) game.getState().getValue(source.getSourceId().toString() + "firstChoice")).getDescription();
game.informPlayers(mageObject.getName()
+ ": First chosen basic land type is " + choices.getChoice());
game.getState().setValue(mageObject.getId().toString()
+ "firstChoice", choices.getChoice());
choiceOne = SubType.byDescription((String) game.getState().getValue(
source.getSourceId().toString() + "firstChoice")).getDescription();
}
if (controller.choose(Outcome.Neutral, choices, game)) {
game.informPlayers(mageObject.getName() + ": Second chosen basic land type is " + choices.getChoice());
game.getState().setValue(mageObject.getId().toString() + "secondChoice", choices.getChoice());
choiceTwo = SubType.byDescription((String) game.getState().getValue(source.getSourceId().toString() + "secondChoice")).getDescription();
game.informPlayers(mageObject.getName()
+ ": Second chosen basic land type is " + choices.getChoice());
game.getState().setValue(mageObject.getId().toString()
+ "secondChoice", choices.getChoice());
choiceTwo = SubType.byDescription((String) game.getState().getValue(
source.getSourceId().toString() + "secondChoice")).getDescription();
if (mageObject instanceof Permanent
&& choiceOne != null
&& choiceTwo != null) {
((Permanent) mageObject).addInfo("Chosen Types", CardUtil.addToolTipMarkTags("First chosen basic land type: " + choiceOne
+ "\n Second chosen basic land type: " + choiceTwo), game);
((Permanent) mageObject).addInfo("Chosen Types", CardUtil
.addToolTipMarkTags("First chosen basic land type: " + choiceOne
+ "\n Second chosen basic land type: " + choiceTwo), game);
}
return true;
}

View file

@ -1,8 +1,6 @@
package mage.cards.k;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.common.continuous.BecomesCreatureAllEffect;
@ -10,8 +8,6 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.filter.FilterPermanent;
import mage.game.permanent.token.TokenImpl;
import mage.game.permanent.token.Token;
import mage.game.permanent.token.custom.CreatureToken;
/**
@ -27,10 +23,13 @@ public final class KormusBell extends CardImpl {
// All Swamps are 1/1 black creatures that are still lands.
ContinuousEffect effect = new BecomesCreatureAllEffect(
new CreatureToken(1, 1, "1/1 black creature").withColor("B"),
"lands", new FilterPermanent(SubType.SWAMP, "Swamps"), Duration.WhileOnBattlefield, true);
effect.setDependedToType(DependencyType.BecomeSwamp);
"lands", new FilterPermanent(SubType.SWAMP, "Swamps"),
Duration.WhileOnBattlefield, true);
effect.addDependedToType(DependencyType.BecomeSwamp);
effect.addDependedToType(DependencyType.BecomeIsland);
effect.addDependedToType(DependencyType.BecomeForest);
effect.addDependedToType(DependencyType.BecomeMountain);
effect.addDependedToType(DependencyType.BecomePlains);
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect));
}

View file

@ -1,4 +1,3 @@
package mage.cards.m;
import java.util.UUID;
@ -30,8 +29,10 @@ public final class MycosynthLattice extends CardImpl {
// All permanents are artifacts in addition to their other types.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new PermanentsAreArtifactsEffect()));
// All cards that aren't on the battlefield, spells, and permanents are colorless.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new EverythingIsColorlessEffect()));
// Players may spend mana as though it were mana of any color.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ManaCanBeSpentAsAnyColorEffect()));
}
@ -51,6 +52,7 @@ class PermanentsAreArtifactsEffect extends ContinuousEffectImpl {
public PermanentsAreArtifactsEffect() {
super(Duration.WhileOnBattlefield, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Neutral);
staticText = "All permanents are artifacts in addition to their other types";
this.dependencyTypes.add(DependencyType.ArtifactAddingRemoving); // March of the Machines
}
@Override

View file

@ -31,7 +31,8 @@ public final class NecroticOoze extends CardImpl {
this.power = new MageInt(4);
this.toughness = new MageInt(3);
// As long as Necrotic Ooze is on the battlefield, it has all activated abilities of all creature cards in all graveyards
// As long as Necrotic Ooze is on the battlefield, it has all
// activated abilities of all creature cards in all graveyards
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new NecroticOozeEffect()));
}
@ -47,8 +48,10 @@ public final class NecroticOoze extends CardImpl {
static class NecroticOozeEffect extends ContinuousEffectImpl {
public NecroticOozeEffect() {
super(Duration.WhileOnBattlefield, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility);
staticText = "As long as {this} is on the battlefield, it has all activated abilities of all creature cards in all graveyards";
super(Duration.WhileOnBattlefield,
Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility);
staticText = "As long as {this} is on the battlefield, "
+ "it has all activated abilities of all creature cards in all graveyards";
}
public NecroticOozeEffect(final NecroticOozeEffect effect) {
@ -65,8 +68,11 @@ public final class NecroticOoze extends CardImpl {
for (Card card : player.getGraveyard().getCards(game)) {
if (card.isCreature()) {
for (Ability ability : card.getAbilities(game)) {
if (ability instanceof ActivatedAbility) {
perm.addAbility(ability, source.getSourceId(), game);
if (ability instanceof ActivatedAbility
&& !perm.getAbilities().contains(ability)) {
if (!perm.getAbilities().contains(ability)) {
perm.addAbility(ability, source.getSourceId(), game);
}
}
}
}

View file

@ -1,15 +1,14 @@
package mage.cards.o;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.abilities.effects.Effect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
@ -26,9 +25,10 @@ import mage.game.permanent.Permanent;
public final class Opalescence extends CardImpl {
public Opalescence(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{W}{W}");
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}{W}");
// Each other non-Aura enchantment is a creature with power and toughness each equal to its converted mana cost. It's still an enchantment.
// Each other non-Aura enchantment is a creature with power and
// toughness each equal to its converted mana cost. It's still an enchantment.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new OpalescenceEffect()));
}
@ -42,77 +42,75 @@ public final class Opalescence extends CardImpl {
return new Opalescence(this);
}
}
// needs to enclosed with the card class due to a dependency check by cards like Conspiracy
static class OpalescenceEffect extends ContinuousEffectImpl {
class OpalescenceEffect extends ContinuousEffectImpl {
private static final FilterEnchantmentPermanent filter
= new FilterEnchantmentPermanent("Each other non-Aura enchantment");
private static final FilterEnchantmentPermanent filter = new FilterEnchantmentPermanent("Each other non-Aura enchantment");
private static final EnumSet checkDependencyTypes;
static {
filter.add(Predicates.not(SubType.AURA.getPredicate()));
filter.add(AnotherPredicate.instance);
}
static {
filter.add(Predicates.not(SubType.AURA.getPredicate()));
filter.add(AnotherPredicate.instance);
checkDependencyTypes = EnumSet.of(DependencyType.AuraAddingRemoving, DependencyType.EnchantmentAddingRemoving);
}
public OpalescenceEffect() {
super(Duration.WhileOnBattlefield, Outcome.BecomeCreature);
staticText = "Each other non-Aura enchantment is a creature in addition to its other "
+ "types and has base power and base toughness each equal to its converted mana cost";
}
public OpalescenceEffect() {
super(Duration.WhileOnBattlefield, Outcome.BecomeCreature);
staticText = "Each other non-Aura enchantment is a creature in addition to its other types and has base power and base toughness each equal to its converted mana cost";
}
public OpalescenceEffect(final OpalescenceEffect effect) {
super(effect);
}
public OpalescenceEffect(final OpalescenceEffect effect) {
super(effect);
}
@Override
public OpalescenceEffect copy() {
return new OpalescenceEffect(this);
}
@Override
public OpalescenceEffect copy() {
return new OpalescenceEffect(this);
}
@Override
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) {
switch (layer) {
case TypeChangingEffects_4:
if (sublayer == SubLayer.NA) {
if (!permanent.isCreature()) {
permanent.addCardType(CardType.CREATURE);
@Override
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) {
switch (layer) {
case TypeChangingEffects_4:
if (sublayer == SubLayer.NA) {
if (!permanent.isCreature()) {
permanent.addCardType(CardType.CREATURE);
}
}
}
break;
break;
case PTChangingEffects_7:
if (sublayer == SubLayer.SetPT_7b) {
int manaCost = permanent.getConvertedManaCost();
permanent.getPower().setValue(manaCost);
permanent.getToughness().setValue(manaCost);
}
}
}
return true;
}
@Override
public boolean apply(Game game, Ability source) {
return false;
}
@Override
public boolean hasLayer(Layer layer) {
return layer == Layer.PTChangingEffects_7 || layer == Layer.TypeChangingEffects_4;
}
@Override
public Set<UUID> isDependentTo(List<ContinuousEffect> allEffectsInLayer) {
Set<UUID> dependentTo = new HashSet<>();
for (ContinuousEffect effect : allEffectsInLayer) {
for (DependencyType dependencyType : effect.getDependencyTypes()) {
if (checkDependencyTypes.contains(dependencyType)) {
dependentTo.add(effect.getId());
case PTChangingEffects_7:
if (sublayer == SubLayer.SetPT_7b) {
int manaCost = permanent.getConvertedManaCost();
permanent.getPower().setValue(manaCost);
permanent.getToughness().setValue(manaCost);
}
}
}
return true;
}
@Override
public boolean apply(Game game, Ability source) {
return false;
}
@Override
public boolean hasLayer(Layer layer) {
return layer == Layer.PTChangingEffects_7
|| layer == Layer.TypeChangingEffects_4;
}
@Override
public Set<UUID> isDependentTo(List<ContinuousEffect> allEffectsInLayer) {
// the dependent classes needs to be an enclosed class for dependent check of continuous effects
return allEffectsInLayer.stream()
.filter(effect -> effect.getDependencyTypes().contains(DependencyType.EnchantmentAddingRemoving)
|| effect.getDependencyTypes().contains(DependencyType.AuraAddingRemoving)) // Cloudform
.map(Effect::getId)
.collect(Collectors.toSet());
}
return dependentTo;
}
}

View file

@ -1,4 +1,3 @@
package mage.cards.p;
import java.util.UUID;
@ -17,6 +16,7 @@ import mage.abilities.mana.WhiteManaAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.DependencyType;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.Layer;
@ -59,74 +59,90 @@ public final class PhantasmalTerrain extends CardImpl {
public PhantasmalTerrain copy() {
return new PhantasmalTerrain(this);
}
}
class PhantasmalTerrainContinuousEffect extends ContinuousEffectImpl {
class PhantasmalTerrainContinuousEffect extends ContinuousEffectImpl {
public PhantasmalTerrainContinuousEffect() {
super(Duration.WhileOnBattlefield, Outcome.Neutral);
this.staticText = "enchanted land is the chosen type";
}
public PhantasmalTerrainContinuousEffect(final PhantasmalTerrainContinuousEffect effect) {
super(effect);
}
@Override
public PhantasmalTerrainContinuousEffect copy() {
return new PhantasmalTerrainContinuousEffect(this);
}
@Override
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
Permanent enchantment = game.getPermanent(source.getSourceId());
SubType choice = SubType.byDescription((String) game.getState().getValue(source.getSourceId().toString() + ChooseBasicLandTypeEffect.VALUE_KEY));
if (enchantment != null && enchantment.getAttachedTo() != null && choice != null) {
Permanent land = game.getPermanent(enchantment.getAttachedTo());
if (land != null) {
switch (layer) {
case TypeChangingEffects_4:
if (sublayer == SubLayer.NA) {
land.getSubtype(game).clear();
land.getSubtype(game).add(choice);
}
break;
case AbilityAddingRemovingEffects_6:
if (sublayer == SubLayer.NA) {
land.getAbilities().clear();
if (choice.equals(SubType.FOREST)) {
land.addAbility(new GreenManaAbility(), source.getSourceId(), game);
}
if (choice.equals(SubType.PLAINS)) {
land.addAbility(new WhiteManaAbility(), source.getSourceId(), game);
}
if (choice.equals(SubType.MOUNTAIN)) {
land.addAbility(new RedManaAbility(), source.getSourceId(), game);
}
if (choice.equals(SubType.ISLAND)) {
land.addAbility(new BlueManaAbility(), source.getSourceId(), game);
}
if (choice.equals(SubType.SWAMP)) {
land.addAbility(new BlackManaAbility(), source.getSourceId(), game);
}
}
break;
}
return true;
}
public PhantasmalTerrainContinuousEffect() {
super(Duration.WhileOnBattlefield, Outcome.Neutral);
this.staticText = "enchanted land is the chosen type";
}
return false;
}
@Override
public boolean apply(Game game, Ability source) {
return false;
}
public PhantasmalTerrainContinuousEffect(final PhantasmalTerrainContinuousEffect effect) {
super(effect);
}
@Override
public boolean hasLayer(Layer layer) {
return layer == Layer.AbilityAddingRemovingEffects_6
|| layer == Layer.TypeChangingEffects_4;
}
@Override
public PhantasmalTerrainContinuousEffect copy() {
return new PhantasmalTerrainContinuousEffect(this);
}
@Override
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
Permanent enchantment = game.getPermanent(source.getSourceId());
SubType choice = SubType.byDescription((String) game.getState()
.getValue(source.getSourceId().toString() + ChooseBasicLandTypeEffect.VALUE_KEY));
if (choice != null) {
if (choice.equals(SubType.MOUNTAIN)) {
dependencyTypes.add(DependencyType.BecomeMountain);
}
if (choice.equals(SubType.FOREST)) {
dependencyTypes.add(DependencyType.BecomeForest);
}
if (choice.equals(SubType.SWAMP)) {
dependencyTypes.add(DependencyType.BecomeSwamp);
}
if (choice.equals(SubType.ISLAND)) {
dependencyTypes.add(DependencyType.BecomeIsland);
}
if (choice.equals(SubType.PLAINS)) {
dependencyTypes.add(DependencyType.BecomePlains);
}
}
if (enchantment != null
&& enchantment.getAttachedTo() != null
&& choice != null) {
Permanent land = game.getPermanent(enchantment.getAttachedTo());
if (land != null) {
switch (layer) {
case TypeChangingEffects_4:
if (sublayer == SubLayer.NA) {
land.getSubtype(game).clear();
land.getSubtype(game).add(choice);
land.removeAllAbilities(source.getSourceId(), game);
// land ability is intrinsic, so apply at this layer, not layer 6
if (choice.equals(SubType.FOREST)) {
land.addAbility(new GreenManaAbility(), source.getSourceId(), game);
}
if (choice.equals(SubType.PLAINS)) {
land.addAbility(new WhiteManaAbility(), source.getSourceId(), game);
}
if (choice.equals(SubType.MOUNTAIN)) {
land.addAbility(new RedManaAbility(), source.getSourceId(), game);
}
if (choice.equals(SubType.ISLAND)) {
land.addAbility(new BlueManaAbility(), source.getSourceId(), game);
}
if (choice.equals(SubType.SWAMP)) {
land.addAbility(new BlackManaAbility(), source.getSourceId(), game);
}
}
break;
}
return true;
}
}
return false;
}
@Override
public boolean apply(Game game, Ability source) {
return false;
}
@Override
public boolean hasLayer(Layer layer) {
return layer == Layer.TypeChangingEffects_4;
}
}
}

View file

@ -13,7 +13,6 @@ import mage.abilities.effects.common.continuous.BecomesBasicLandTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.DependencyType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.SubType;
@ -81,7 +80,9 @@ class QuicksilverFountainEffect extends OneShotEffect {
public QuicksilverFountainEffect() {
super(Outcome.Neutral);
staticText = "that player puts a flood counter on target non-Island land they control of their choice. That land is an Island for as long as it has a flood counter on it";
staticText = "that player puts a flood counter on target non-Island land "
+ "they control of their choice. That land is an Island for as "
+ "long as it has a flood counter on it";
}
public QuicksilverFountainEffect(final QuicksilverFountainEffect effect) {
@ -94,9 +95,11 @@ class QuicksilverFountainEffect extends OneShotEffect {
if (player != null) {
Permanent landChosen = game.getPermanent(source.getFirstTarget());
landChosen.addCounters(CounterType.FLOOD.createInstance(), source, game);
ContinuousEffect becomesBasicLandTargetEffect = new BecomesBasicLandTargetEffect(Duration.OneUse, SubType.ISLAND);
becomesBasicLandTargetEffect.addDependencyType(DependencyType.BecomeIsland);
ConditionalContinuousEffect effect = new ConditionalContinuousEffect(becomesBasicLandTargetEffect, new LandHasFloodCounterCondition(this), staticText);
ContinuousEffect becomesBasicLandTargetEffect
= new BecomesBasicLandTargetEffect(Duration.OneUse, false, SubType.ISLAND);
ConditionalContinuousEffect effect
= new ConditionalContinuousEffect(becomesBasicLandTargetEffect,
new LandHasFloodCounterCondition(this), staticText);
this.setTargetPointer(new FixedTarget(landChosen, game));
effect.setTargetPointer(new FixedTarget(landChosen, game));
game.addEffect(effect, source);

View file

@ -18,6 +18,8 @@ import mage.target.TargetPermanent;
import mage.target.common.TargetLandPermanent;
import java.util.UUID;
import mage.abilities.effects.ContinuousEffect;
import mage.constants.DependencyType;
/**
*
@ -41,7 +43,9 @@ public final class SpreadingSeas extends CardImpl {
this.addAbility(new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1), false));
// Enchanted land is an Island.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BecomesBasicLandEnchantedEffect(SubType.ISLAND)));
ContinuousEffect effect = new BecomesBasicLandEnchantedEffect(SubType.ISLAND);
effect.addDependencyType(DependencyType.BecomeIsland);
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect));
}

View file

@ -7,8 +7,6 @@ import java.util.stream.Collectors;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition;
import mage.abilities.decorator.ConditionalContinuousEffect;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.abilities.effects.Effect;
@ -17,6 +15,7 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.filter.FilterCard;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterEnchantmentPermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.permanent.AnotherPredicate;
@ -60,9 +59,7 @@ public final class StarfieldOfNyx extends CardImpl {
// As long as you control five or more enchantments, each other non-Aura enchantment
// you control is a creature in addition to its other types and has base power and
// base toughness each equal to its converted mana cost.
ConditionalContinuousEffect effect = new ConditionalContinuousEffect(
new StarfieldOfNyxEffect(), new PermanentsOnTheBattlefieldCondition(
filterEnchantmentYouControl, ComparisonType.MORE_THAN, 4), rule1);
ContinuousEffect effect = new StarfieldOfNyxEffect();
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect));
}
@ -74,79 +71,88 @@ public final class StarfieldOfNyx extends CardImpl {
public StarfieldOfNyx copy() {
return new StarfieldOfNyx(this);
}
}
class StarfieldOfNyxEffect extends ContinuousEffectImpl {
static class StarfieldOfNyxEffect extends ContinuousEffectImpl {
private static final FilterEnchantmentPermanent filter
= new FilterEnchantmentPermanent("Each other non-Aura enchantment you control");
static {
filter.add(Predicates.not(SubType.AURA.getPredicate()));
filter.add(AnotherPredicate.instance);
filter.add(TargetController.YOU.getControllerPredicate());
}
public StarfieldOfNyxEffect() {
super(Duration.WhileOnBattlefield, Outcome.BecomeCreature);
staticText = "Each other non-Aura enchantment you control is a creature "
+ "in addition to its other types and has base power and "
+ "toughness each equal to its converted mana cost";
}
public StarfieldOfNyxEffect(final StarfieldOfNyxEffect effect) {
super(effect);
}
@Override
public StarfieldOfNyxEffect copy() {
return new StarfieldOfNyxEffect(this);
}
@Override
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter,
source.getControllerId(), source.getSourceId(), game)) {
switch (layer) {
case TypeChangingEffects_4:
if (sublayer == SubLayer.NA) {
if (!permanent.isCreature()) {
permanent.addCardType(CardType.CREATURE);
}
}
break;
case PTChangingEffects_7:
if (sublayer == SubLayer.SetPT_7b) {
int manaCost = permanent.getConvertedManaCost();
permanent.getPower().setValue(manaCost);
permanent.getToughness().setValue(manaCost);
}
}
private static final FilterPermanent filter
= new FilterPermanent("Each other non-Aura enchantment you control");
private static final FilterEnchantmentPermanent filter2
= new FilterEnchantmentPermanent();
static {
filter2.add(TargetController.YOU.getControllerPredicate());
}
return true;
}
@Override
public boolean apply(Game game, Ability source) {
return false;
}
public StarfieldOfNyxEffect() {
super(Duration.WhileOnBattlefield, Outcome.BecomeCreature);
staticText = "Each other non-Aura enchantment you control is a creature "
+ "in addition to its other types and has base power and "
+ "toughness each equal to its converted mana cost";
}
@Override
public boolean hasLayer(Layer layer) {
return layer == Layer.PTChangingEffects_7
|| layer == Layer.TypeChangingEffects_4;
}
public StarfieldOfNyxEffect(final StarfieldOfNyxEffect effect) {
super(effect);
}
@Override
public Set<UUID> isDependentTo(List<ContinuousEffect> allEffectsInLayer) {
return allEffectsInLayer
.stream()
.filter(effect -> effect.getDependencyTypes().contains(DependencyType.AuraAddingRemoving)
|| effect.getDependencyTypes().contains(DependencyType.EnchantmentAddingRemoving)) // example: Enchanted Evening
.map(Effect::getId)
.collect(Collectors.toSet());
@Override
public StarfieldOfNyxEffect copy() {
return new StarfieldOfNyxEffect(this);
}
@Override
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
filter.add(CardType.ENCHANTMENT.getPredicate());
filter.add(Predicates.not(SubType.AURA.getPredicate()));
filter.add(AnotherPredicate.instance);
if (game.getState().getBattlefield().getActivePermanents(filter2,
source.getControllerId(), source.getSourceId(), game).size() > 4) {
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter,
source.getControllerId(), source.getSourceId(), game)) {
switch (layer) {
case TypeChangingEffects_4:
if (sublayer == SubLayer.NA) {
if (!permanent.isCreature()
&& !permanent.getSubtype(game).contains(SubType.AURA)) {
permanent.addCardType(CardType.CREATURE);
}
}
break;
case PTChangingEffects_7:
if (sublayer == SubLayer.SetPT_7b
&& permanent.isCreature()
&& !permanent.getSubtype(game).contains(SubType.AURA)) {
int manaCost = permanent.getConvertedManaCost();
permanent.getPower().setValue(manaCost);
permanent.getToughness().setValue(manaCost);
}
}
}
return true;
}
return false;
}
@Override
public boolean apply(Game game, Ability source) {
return false;
}
@Override
public boolean hasLayer(Layer layer) {
return layer == Layer.PTChangingEffects_7
|| layer == Layer.TypeChangingEffects_4;
}
@Override
public Set<UUID> isDependentTo(List<ContinuousEffect> allEffectsInLayer) {
// the dependent classes needs to be an enclosed class for dependent check of continuous effects
return allEffectsInLayer.stream()
.filter(effect -> effect.getDependencyTypes().contains(DependencyType.EnchantmentAddingRemoving)
|| effect.getDependencyTypes().contains(DependencyType.AuraAddingRemoving)) // Cloudform
.map(Effect::getId)
.collect(Collectors.toSet());
}
}
}

View file

@ -1,5 +1,3 @@
package mage.cards.s;
import java.util.UUID;
@ -14,6 +12,7 @@ import mage.abilities.mana.BlueManaAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.DependencyType;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.Layer;
@ -41,7 +40,7 @@ public final class StormtideLeviathan extends CardImpl {
}
public StormtideLeviathan(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{5}{U}{U}{U}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{U}{U}{U}");
this.subtype.add(SubType.LEVIATHAN);
this.power = new MageInt(8);
@ -52,7 +51,8 @@ public final class StormtideLeviathan extends CardImpl {
// All lands are Islands in addition to their other types.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new StormtideLeviathanEffect()));
// Creatures without flying or islandwalk can't attack.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantAttackAnyPlayerAllEffect(Duration.WhileOnBattlefield, filter)));
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
new CantAttackAnyPlayerAllEffect(Duration.WhileOnBattlefield, filter)));
}
@ -65,57 +65,50 @@ public final class StormtideLeviathan extends CardImpl {
return new StormtideLeviathan(this);
}
}
class StormtideLeviathanEffect extends ContinuousEffectImpl {
class StormtideLeviathanEffect extends ContinuousEffectImpl {
public StormtideLeviathanEffect() {
super(Duration.WhileOnBattlefield, Outcome.Neutral);
staticText = "All lands are Islands in addition to their other types";
}
public StormtideLeviathanEffect(final StormtideLeviathanEffect effect) {
super(effect);
}
@Override
public StormtideLeviathanEffect copy() {
return new StormtideLeviathanEffect(this);
}
@Override
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
for (Permanent land : game.getBattlefield().getActivePermanents(new FilterLandPermanent(), source.getControllerId(), game)) {
switch (layer) {
case TypeChangingEffects_4:
if (!land.hasSubtype(SubType.ISLAND, game)) {
land.getSubtype(game).add(SubType.ISLAND);
}
break;
case AbilityAddingRemovingEffects_6:
boolean addAbility = true;
for (Ability existingAbility : land.getAbilities()) {
if (existingAbility instanceof BlueManaAbility) {
addAbility = false;
break;
}
}
if (addAbility) {
land.addAbility(new BlueManaAbility(), source.getSourceId(), game);
}
break;
}
public StormtideLeviathanEffect() {
super(Duration.WhileOnBattlefield, Outcome.Neutral);
staticText = "All lands are Islands in addition to their other types";
this.dependencyTypes.add(DependencyType.BecomeIsland);
}
return true;
}
@Override
public boolean apply(Game game, Ability source) {
return false;
}
public StormtideLeviathanEffect(final StormtideLeviathanEffect effect) {
super(effect);
}
@Override
public boolean hasLayer(Layer layer) {
return layer == Layer.AbilityAddingRemovingEffects_6 || layer == Layer.TypeChangingEffects_4;
@Override
public StormtideLeviathanEffect copy() {
return new StormtideLeviathanEffect(this);
}
@Override
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
for (Permanent land : game.getBattlefield().getActivePermanents(
new FilterLandPermanent(), source.getControllerId(), game)) {
switch (layer) {
case TypeChangingEffects_4:
// land abilities are intrinsic, so add them here, not in layer 6
if (!land.hasSubtype(SubType.ISLAND, game)) {
land.getSubtype(game).add(SubType.ISLAND);
if (!land.getAbilities(game).contains(new BlueManaAbility())) {
land.addAbility(new BlueManaAbility(), source.getSourceId(), game);
}
}
break;
}
}
return true;
}
@Override
public boolean apply(Game game, Ability source) {
return false;
}
@Override
public boolean hasLayer(Layer layer) {
return layer == Layer.TypeChangingEffects_4;
}
}
}

View file

@ -1,17 +1,29 @@
package mage.cards.u;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.continuous.AddCardSubtypeAllEffect;
import mage.abilities.effects.common.continuous.GainAbilityAllEffect;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.abilities.effects.Effect;
import mage.abilities.mana.BlackManaAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.constants.CardType;
import mage.constants.DependencyType;
import mage.constants.Duration;
import mage.constants.Layer;
import static mage.constants.Layer.TypeChangingEffects_4;
import mage.constants.Outcome;
import mage.constants.SubLayer;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.filter.common.FilterLandPermanent;
import java.util.UUID;
import mage.game.Game;
import mage.game.permanent.Permanent;
/**
*
@ -20,13 +32,11 @@ import java.util.UUID;
public final class UrborgTombOfYawgmoth extends CardImpl {
public UrborgTombOfYawgmoth(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.LAND},"");
super(ownerId, setInfo, new CardType[]{CardType.LAND}, "");
addSuperType(SuperType.LEGENDARY);
// Each land is a Swamp in addition to its other land types.
Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAllEffect(new BlackManaAbility(), Duration.WhileOnBattlefield, new FilterLandPermanent(),
"Each land is a Swamp in addition to its other land types"));
ability.addEffect(new AddCardSubtypeAllEffect(new FilterLandPermanent(), SubType.SWAMP, DependencyType.BecomeSwamp));
Ability ability = new SimpleStaticAbility(new UrborgTombOfYawgmothEffect());
this.addAbility(ability);
}
@ -39,4 +49,62 @@ public final class UrborgTombOfYawgmoth extends CardImpl {
public UrborgTombOfYawgmoth copy() {
return new UrborgTombOfYawgmoth(this);
}
class UrborgTombOfYawgmothEffect extends ContinuousEffectImpl {
UrborgTombOfYawgmothEffect() {
super(Duration.WhileOnBattlefield, Outcome.AIDontUseIt);
this.staticText = "Each land is a Swamp in addition to its other land types";
this.dependencyTypes.add(DependencyType.BecomeSwamp);
}
UrborgTombOfYawgmothEffect(final UrborgTombOfYawgmothEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
return false;
}
@Override
public UrborgTombOfYawgmothEffect copy() {
return new UrborgTombOfYawgmothEffect(this);
}
@Override
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
for (Permanent land : game.getBattlefield().getActivePermanents(new FilterLandPermanent(), source.getControllerId(), game)) {
switch (layer) {
case TypeChangingEffects_4:
// 305.7 Note that this doesn't remove any abilities that were granted to the land by other effects
// So the ability removing has to be done before Layer 6
// Lands have their mana ability intrinsically, so that is added in layer 4
if (!land.getSubtype(game).contains(SubType.SWAMP)) {
land.getSubtype(game).add(SubType.SWAMP);
}
if (!land.getAbilities().containsRule(new BlackManaAbility())) {
land.addAbility(new BlackManaAbility(), source.getSourceId(), game);
}
break;
}
}
return true;
}
@Override
public boolean hasLayer(Layer layer) {
return layer == Layer.TypeChangingEffects_4;
}
@Override
public Set<UUID> isDependentTo(List<ContinuousEffect> allEffectsInLayer) {
// the dependent classes needs to be an enclosed class for dependent check of continuous effects
return allEffectsInLayer.stream()
.filter(effect -> mage.cards.b.BloodMoon.class.equals(effect.getClass().getEnclosingClass()))
.map(Effect::getId)
.collect(Collectors.toSet()); // Blood Moon affects non-basic land like Urborg
}
}
}

View file

@ -21,7 +21,8 @@ public class DependentEffectsTest extends CardTestPlayerBase {
*/
@Test
public void testLandsAreDestroyed() {
// Each other non-Aura enchantment is a creature in addition to its other types and has base power and base toughness each equal to its converted mana cost.
// Each other non-Aura enchantment is a creature in addition to its other types
// and has base power and base toughness each equal to its converted mana cost.
addCard(Zone.HAND, playerA, "Opalescence", 1); // {2}{W}{W}
addCard(Zone.BATTLEFIELD, playerA, "Plains", 9);
@ -34,9 +35,10 @@ public class DependentEffectsTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Opalescence");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Enchanted Evening");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertAllCommandsUsed();
assertPowerToughness(playerA, "Enchanted Evening", 5, 5);
assertPowerToughness(playerA, "War Horn", 3, 3);
@ -46,7 +48,7 @@ public class DependentEffectsTest extends CardTestPlayerBase {
}
/**
* Opalescense is dependent on Enchanted Evening, so it will be applied
* Opalescence is dependent on Enchanted Evening, so it will be applied
* after it regardless of timestamp.
*
* Tokens can also have mana costs, and as a consequence of that, converted
@ -81,6 +83,7 @@ public class DependentEffectsTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Enchanted Evening");
setStopAt(1, PhaseStep.END_TURN);
execute();
assertAllCommandsUsed();
assertGraveyardCount(playerA, "Rite of Replication", 1);
assertGraveyardCount(playerB, "Raise the Alarm", 1);
@ -132,8 +135,11 @@ public class DependentEffectsTest extends CardTestPlayerBase {
addCard(Zone.HAND, playerA, "Yixlid Jailer", 1); // Creature - {1}{B}
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Yixlid Jailer");
setStrictChooseMode(true);
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertAllCommandsUsed();
assertPermanentCount(playerA, "Yixlid Jailer", 1);

View file

@ -198,11 +198,14 @@ public class LandTypeChangingEffectsTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Kormus Bell");
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Quicksilver Fountain");
addTarget(playerA, "Mountain");
setStrictChooseMode(true);
setStopAt(3, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertAllCommandsUsed();
assertPermanentCount(playerA, urborgtoy, 1);
assertPermanentCount(playerA, "Kormus Bell", 1);
assertPermanentCount(playerB, "Quicksilver Fountain", 1);

View file

@ -16,6 +16,77 @@ import org.mage.test.serverside.base.CardTestPlayerBase;
* @author jeffwadsworth
*/
public class LayerTests extends CardTestPlayerBase {
@Test
public void testMultipleLayeredDependency() {
//Conspiracy->Opalescence->Enchanted Evening
//Conspiracy is dependent on Opalescence
//Opalescence is dependent on Enchanted Evening
//So, the effects should be applied as follows:
//Enchanted Evening->Opalescence->Conspiracy
addCard(Zone.HAND, playerA, "Conspiracy"); // creatures get chosen subtype
addCard(Zone.HAND, playerA, "Opalescence"); // enchantments become creatures P/T equal to CMC
addCard(Zone.HAND, playerA, "Enchanted Evening"); // all permanents become enchantments
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 5);
addCard(Zone.BATTLEFIELD, playerA, "Plains", 5);
addCard(Zone.BATTLEFIELD, playerA, "Island", 5);
addCard(Zone.BATTLEFIELD, playerA, "Glorious Anthem", 1); // keep lands alive // all creatures +1/+1
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Conspiracy");
setChoice(playerA, "Advisor");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Opalescence");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Enchanted Evening");
setStrictChooseMode(true);
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertAllCommandsUsed();
assertType("Swamp", CardType.LAND, SubType.ADVISOR); // Subtype changed with Conspiracy
assertPowerToughness(playerA, "Swamp", 1, 1); // boosted with Glorious Anthem
assertType("Enchanted Evening", CardType.ENCHANTMENT, SubType.ADVISOR); // Subtype changed with Conspiracy
assertPowerToughness(playerA, "Enchanted Evening", 6, 6); // boosted with Glorious Anthem
}
@Test
public void testMycosynthLatticeAndMarchOfTheMachinesAndHumility() {
// example from Reddit
/*
This came up in a recent EDH game and we had no idea how to progress.
Player A cast a Humility, then a March of the Machines, and finally
a Mycosynth Lattice.
Does the game get stuck in an endless loop of each card gaining and
losing its respective creature-ness and abilities?
Answer: No, they all die
*/
addCard(Zone.HAND, playerA, "Mycosynth Lattice"); // all permanents are artifacts
addCard(Zone.HAND, playerA, "March of the Machines"); // artifacts become creatures
addCard(Zone.HAND, playerA, "Humility"); // all creatures lose abilities and P/T is 1/1
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 10);
addCard(Zone.BATTLEFIELD, playerA, "Plains", 10);
addCard(Zone.BATTLEFIELD, playerA, "Island", 10);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Humility");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "March of the Machines");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Mycosynth Lattice");
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertAllCommandsUsed();
// everything dies
assertPermanentCount(playerA, "Humility", 0);
assertPermanentCount(playerA, "March of the Machines", 0);
assertPermanentCount(playerA, "Mycosynth Lattice", 0);
assertPermanentCount(playerA, "Island", 0);
}
@Test
public void testBloodMoon_UrborgTombOfYawgmothInteraction() {
// Blood Moon : Nonbasic lands are Mountains.

View file

@ -168,8 +168,12 @@ public abstract class ContinuousEffectImpl extends EffectImpl implements Continu
case PTChangingEffects_7:
this.affectedObjectsSet = true;
}
} else if (hasLayer(Layer.CopyEffects_1) || hasLayer(Layer.ControlChangingEffects_2) || hasLayer(Layer.TextChangingEffects_3)
|| hasLayer(Layer.TypeChangingEffects_4) || hasLayer(Layer.ColorChangingEffects_5) || hasLayer(Layer.AbilityAddingRemovingEffects_6)
} else if (hasLayer(Layer.CopyEffects_1)
|| hasLayer(Layer.ControlChangingEffects_2)
|| hasLayer(Layer.TextChangingEffects_3)
|| hasLayer(Layer.TypeChangingEffects_4)
|| hasLayer(Layer.ColorChangingEffects_5)
|| hasLayer(Layer.AbilityAddingRemovingEffects_6)
|| hasLayer(Layer.PTChangingEffects_7)) {
this.affectedObjectsSet = true;
}
@ -185,7 +189,8 @@ public abstract class ContinuousEffectImpl extends EffectImpl implements Continu
@Override
public void setStartingControllerAndTurnNum(Game game, UUID startingController, UUID activePlayerId) {
this.startingControllerId = startingController;
this.startingTurnWasActive = activePlayerId != null && activePlayerId.equals(startingController); // you can't use "game" for active player cause it's called from tests/cheat too
this.startingTurnWasActive = activePlayerId != null
&& activePlayerId.equals(startingController); // you can't use "game" for active player cause it's called from tests/cheat too
this.yourTurnNumPlayed = 0;
}
@ -197,9 +202,11 @@ public abstract class ContinuousEffectImpl extends EffectImpl implements Continu
@Override
public boolean isYourNextTurn(Game game) {
if (this.startingTurnWasActive) {
return yourTurnNumPlayed == 1 && game.isActivePlayer(startingControllerId);
return yourTurnNumPlayed == 1
&& game.isActivePlayer(startingControllerId);
} else {
return yourTurnNumPlayed == 0 && game.isActivePlayer(startingControllerId);
return yourTurnNumPlayed == 0
&& game.isActivePlayer(startingControllerId);
}
}
@ -231,14 +238,18 @@ public abstract class ContinuousEffectImpl extends EffectImpl implements Continu
switch (duration) {
case UntilYourNextTurn:
case UntilEndOfYourNextTurn:
canDelete = player == null || (!player.isInGame() && player.hasReachedNextTurnAfterLeaving());
canDelete = player == null
|| (!player.isInGame()
&& player.hasReachedNextTurnAfterLeaving());
}
// discard on another conditions (start of your turn)
switch (duration) {
case UntilYourNextTurn:
if (player != null && player.isInGame()) {
canDelete = canDelete || this.isYourNextTurn(game);
if (player != null
&& player.isInGame()) {
canDelete = canDelete
|| this.isYourNextTurn(game);
}
}
@ -305,7 +316,7 @@ public abstract class ContinuousEffectImpl extends EffectImpl implements Continu
@Override
public Set<UUID> isDependentTo(List<ContinuousEffect> allEffectsInLayer) {
Set<UUID> dependentToEffects = new HashSet<UUID>();
Set<UUID> dependentToEffects = new HashSet<>();
if (dependendToTypes != null) {
for (ContinuousEffect effect : allEffectsInLayer) {
if (!effect.getId().equals(this.getId())) {
@ -354,7 +365,8 @@ public abstract class ContinuousEffectImpl extends EffectImpl implements Continu
}
/**
* Auto-generates dependencies on different effects (what's apply first and what's apply second)
* Auto-generates dependencies on different effects (what's apply first and
* what's apply second)
*/
public void generateGainAbilityDependencies(Ability abilityToGain, Filter filterToSearch) {
this.addDependencyType(DependencyType.AddingAbility);
@ -369,14 +381,18 @@ public abstract class ContinuousEffectImpl extends EffectImpl implements Continu
}
private void generateGainAbilityDependenciesFromAbility(CompoundAbility compoundAbility) {
if (compoundAbility == null) return;
if (compoundAbility == null) {
return;
}
for (Ability ability : compoundAbility) {
generateGainAbilityDependenciesFromAbility(ability);
}
}
private void generateGainAbilityDependenciesFromAbility(Ability ability) {
if (ability == null) return;
if (ability == null) {
return;
}
// 1. "Is all type" ability (changeling)
// make dependency
@ -386,7 +402,9 @@ public abstract class ContinuousEffectImpl extends EffectImpl implements Continu
}
private void generateGainAbilityDependenciesFromFilter(Filter filter) {
if (filter == null) return;
if (filter == null) {
return;
}
// 1. "Is all type" ability (changeling)
// wait dependency

View file

@ -338,7 +338,7 @@ public class ContinuousEffects implements Serializable {
}
// boolean checkLKI = event.getType().equals(EventType.ZONE_CHANGE) || event.getType().equals(EventType.DESTROYED_PERMANENT);
//get all applicable transient Replacement effects
for (Iterator<ReplacementEffect> iterator = replacementEffects.iterator(); iterator.hasNext(); ) {
for (Iterator<ReplacementEffect> iterator = replacementEffects.iterator(); iterator.hasNext();) {
ReplacementEffect effect = iterator.next();
if (!effect.checksEventType(event, game)) {
continue;
@ -371,7 +371,7 @@ public class ContinuousEffects implements Serializable {
}
}
for (Iterator<PreventionEffect> iterator = preventionEffects.iterator(); iterator.hasNext(); ) {
for (Iterator<PreventionEffect> iterator = preventionEffects.iterator(); iterator.hasNext();) {
PreventionEffect effect = iterator.next();
if (!effect.checksEventType(event, game)) {
continue;
@ -740,8 +740,8 @@ public class ContinuousEffects implements Serializable {
* @param event
* @param targetAbility ability the event is attached to. can be null.
* @param game
* @param silentMode true if the event does not really happen but
* it's checked if the event would be replaced
* @param silentMode true if the event does not really happen but it's
* checked if the event would be replaced
* @return
*/
public boolean preventedByRuleModification(GameEvent event, Ability targetAbility, Game game, boolean silentMode) {
@ -789,7 +789,7 @@ public class ContinuousEffects implements Serializable {
do {
Map<ReplacementEffect, Set<Ability>> rEffects = getApplicableReplacementEffects(event, game);
// Remove all consumed effects (ability dependant)
for (Iterator<ReplacementEffect> it1 = rEffects.keySet().iterator(); it1.hasNext(); ) {
for (Iterator<ReplacementEffect> it1 = rEffects.keySet().iterator(); it1.hasNext();) {
ReplacementEffect entry = it1.next();
if (consumed.containsKey(entry.getId()) /*&& !(entry instanceof CommanderReplacementEffect) */) { // 903.9.
Set<UUID> consumedAbilitiesIds = consumed.get(entry.getId());
@ -980,7 +980,7 @@ public class ContinuousEffects implements Serializable {
if (!waitingEffects.isEmpty()) {
// check if waiting effects can be applied now
for (Iterator<Map.Entry<ContinuousEffect, Set<UUID>>> iterator = waitingEffects.entrySet().iterator(); iterator.hasNext(); ) {
for (Iterator<Map.Entry<ContinuousEffect, Set<UUID>>> iterator = waitingEffects.entrySet().iterator(); iterator.hasNext();) {
Map.Entry<ContinuousEffect, Set<UUID>> entry = iterator.next();
if (appliedEffects.containsAll(entry.getValue())) { // all dependent to effects are applied now so apply the effect itself
appliedAbilities = appliedEffectAbilities.get(entry.getKey());
@ -1060,26 +1060,50 @@ public class ContinuousEffects implements Serializable {
private void applyLayer(List<ContinuousEffect> activeLayerEffects, Layer currentLayer, Game game) {
List<ContinuousEffect> layer = filterLayeredEffects(activeLayerEffects, currentLayer);
// layer is a list of all effects at the current layer
if (!layer.isEmpty()) {
int numberOfEffects = layer.size();
// appliedEffects holds the list of effects currently applied to the layer
Set<UUID> appliedEffects = new HashSet<>();
// waitingEffects holds the list of dependent effects and their independent counterparts
Map<ContinuousEffect, Set<UUID>> waitingEffects = new LinkedHashMap<>();
for (ContinuousEffect effect : layer) {
if (numberOfEffects > 1) { // If an effect is dependent to not applied effects yet of this layer, so wait to apply this effect
if (numberOfEffects > 1) {
// If an effect is dependent to not applied effects yet of this layer, so wait to apply this effect
// check to see if any effect is dependent to other cards indirectly due to the independent card being dependent, etc.
Set<UUID> dependentTo = effect.isDependentTo(layer);
if (!appliedEffects.containsAll(dependentTo)) {
waitingEffects.put(effect, dependentTo);
continue;
}
}
// apply the effect
applyContinuousEffect(effect, currentLayer, game);
// add it to the applied effects list
appliedEffects.add(effect.getId());
layer = getLayeredEffects(game);
// check waiting effects to see if it has anything to check
if (!waitingEffects.isEmpty()) {
// check if waiting effects can be applied now
for (Entry<ContinuousEffect, Set<UUID>> entry : waitingEffects.entrySet()) {
if (appliedEffects.containsAll(entry.getValue())) { // all dependent to effects are applied now so apply the effect itself
// all dependent to effects are applied now so apply the effect itself
if (appliedEffects.containsAll(entry.getValue())) {
applyContinuousEffect(entry.getKey(), currentLayer, game);
// add it to the applied effects list
appliedEffects.add(entry.getKey().getId());
layer = getLayeredEffects(game);
}
}
}
if (numberOfEffects != appliedEffects.size()) {
for (Entry<ContinuousEffect, Set<UUID>> entry : waitingEffects.entrySet()) {
// all dependent to effects are applied now so apply the effect itself
if (appliedEffects.containsAll(entry.getValue())) {
applyContinuousEffect(entry.getKey(), currentLayer, game);
// add it to the applied effects list
appliedEffects.add(entry.getKey().getId());
layer = getLayeredEffects(game);
}
}
}

View file

@ -43,12 +43,15 @@ public class BecomesBasicLandEnchantedEffect extends ContinuousEffectImpl {
Permanent permanent = game.getPermanent(enchantment.getAttachedTo());
if (permanent != null) {
switch (layer) {
case AbilityAddingRemovingEffects_6:
case TypeChangingEffects_4:
// lands intrictically have the mana ability associated with their type, so added here in layer 4
permanent.getSubtype(game).removeAll(SubType.getLandTypes());
permanent.getSubtype(game).addAll(landTypes);
permanent.removeAllAbilities(source.getSourceId(), game);
for (SubType landType : landTypes) {
switch (landType) {
case SWAMP:
if (permanent.hasSubtype(SubType.SWAMP, game)) { // type can be removed by other effect with newer timestamp, so no ability adding
if (permanent.hasSubtype(SubType.SWAMP, game)) {
permanent.addAbility(new BlackManaAbility(), source.getSourceId(), game);
}
break;
@ -75,11 +78,6 @@ public class BecomesBasicLandEnchantedEffect extends ContinuousEffectImpl {
}
}
break;
case TypeChangingEffects_4:
// subtypes are all removed by changing the subtype to a land type.
permanent.getSubtype(game).removeAll(SubType.getLandTypes());
permanent.getSubtype(game).addAll(landTypes);
break;
}
return true;
}
@ -89,7 +87,7 @@ public class BecomesBasicLandEnchantedEffect extends ContinuousEffectImpl {
@Override
public boolean hasLayer(Layer layer) {
return layer == Layer.AbilityAddingRemovingEffects_6 || layer == Layer.TypeChangingEffects_4;
return layer == Layer.TypeChangingEffects_4;
}
private String setText() {

View file

@ -112,7 +112,8 @@ public class BecomesBasicLandTargetEffect extends ContinuousEffectImpl {
land.addCardType(CardType.LAND);
}
if (loseOther) {
// 305.7 Note that this doesn't remove any abilities that were granted to the land by other effects
// 305.7 Note that this doesn't remove any abilities
// that were granted to the land by other effects
// So the ability removing has to be done before Layer 6
land.removeAllAbilities(source.getSourceId(), game);
// 305.7
@ -127,8 +128,7 @@ public class BecomesBasicLandTargetEffect extends ContinuousEffectImpl {
}
}
}
break;
case AbilityAddingRemovingEffects_6:
// add intrinsic land abilities here not in layer 6
for (SubType landType : landTypesToAdd) {
switch (landType) {
case SWAMP:
@ -157,7 +157,7 @@ public class BecomesBasicLandTargetEffect extends ContinuousEffectImpl {
@Override
public boolean hasLayer(Layer layer) {
return layer == Layer.AbilityAddingRemovingEffects_6 || layer == Layer.TypeChangingEffects_4;
return layer == Layer.TypeChangingEffects_4;
}
private String setText() {

View file

@ -25,15 +25,18 @@ public class BecomesCreatureAllEffect extends ContinuousEffectImpl {
private boolean loseTypes = false;
protected boolean loseName = false;
public BecomesCreatureAllEffect(Token token, String theyAreStillType, FilterPermanent filter, Duration duration, boolean loseColor) {
public BecomesCreatureAllEffect(Token token, String theyAreStillType,
FilterPermanent filter, Duration duration, boolean loseColor) {
this(token, theyAreStillType, filter, duration, loseColor, false, false);
}
public BecomesCreatureAllEffect(Token token, String theyAreStillType, FilterPermanent filter, Duration duration, boolean loseColor, boolean loseName) {
public BecomesCreatureAllEffect(Token token, String theyAreStillType,
FilterPermanent filter, Duration duration, boolean loseColor, boolean loseName) {
this(token, theyAreStillType, filter, duration, loseColor, loseName, false);
}
public BecomesCreatureAllEffect(Token token, String theyAreStillType, FilterPermanent filter, Duration duration, boolean loseColor, boolean loseName, boolean loseTypes) {
public BecomesCreatureAllEffect(Token token, String theyAreStillType,
FilterPermanent filter, Duration duration, boolean loseColor, boolean loseName, boolean loseTypes) {
super(duration, Outcome.BecomeCreature);
this.token = token;
this.theyAreStillType = theyAreStillType;
@ -57,7 +60,8 @@ public class BecomesCreatureAllEffect extends ContinuousEffectImpl {
public void init(Ability source, Game game) {
super.init(source, game);
if (this.affectedObjectsSet) {
for (Permanent perm : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) {
for (Permanent perm : game.getBattlefield().getActivePermanents(
filter, source.getControllerId(), source.getSourceId(), game)) {
affectedObjectList.add(new MageObjectReference(perm, game));
}
}
@ -76,7 +80,8 @@ public class BecomesCreatureAllEffect extends ContinuousEffectImpl {
affectedPermanents.add(ref.getPermanent(game));
}
} else {
affectedPermanents = new HashSet<>(game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game));
affectedPermanents = new HashSet<>(game.getBattlefield()
.getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game));
}
for (Permanent permanent : affectedPermanents) {

View file

@ -30,6 +30,13 @@ public class BecomesCreatureAttachedEffect extends ContinuousEffectImpl {
this.loseType = loseType;
staticText = text;
}
public BecomesCreatureAttachedEffect(Token token, String text, Duration duration, LoseType loseType, Outcome outcome) {
super(duration, Layer.TypeChangingEffects_4, SubLayer.NA, outcome);
this.token = token;
this.loseType = loseType;
staticText = text;
}
public BecomesCreatureAttachedEffect(final BecomesCreatureAttachedEffect effect) {
super(effect);