diff --git a/Mage.Sets/src/mage/cards/a/AbuelosAwakening.java b/Mage.Sets/src/mage/cards/a/AbuelosAwakening.java index 26a5957c02f7..35ea00bd78db 100644 --- a/Mage.Sets/src/mage/cards/a/AbuelosAwakening.java +++ b/Mage.Sets/src/mage/cards/a/AbuelosAwakening.java @@ -1,5 +1,6 @@ package mage.cards.a; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.dynamicvalue.common.GetXValue; import mage.abilities.effects.ContinuousEffectImpl; @@ -17,6 +18,8 @@ import mage.target.common.TargetCardInYourGraveyard; import mage.target.targetpointer.FixedTarget; +import java.util.ArrayList; +import java.util.List; import java.util.UUID; /** @@ -106,12 +109,29 @@ public AbuelosAwakeningContinuousEffect copy() { } @Override - public boolean apply(Game game, Ability source) { - return false; + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent creature = (Permanent) object; + switch (layer) { + case TypeChangingEffects_4: + creature.addCardType(game, CardType.CREATURE); + creature.addSubType(game, SubType.SPIRIT); + break; + case AbilityAddingRemovingEffects_6: + creature.addAbility(FlyingAbility.getInstance(), source.getSourceId(), game); + break; + case PTChangingEffects_7: + if (sublayer == SubLayer.SetPT_7b) { + creature.getPower().setModifiedBaseValue(1); + creature.getToughness().setModifiedBaseValue(1); + } + break; + } + } } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Permanent creature; if (source.getTargets().getFirstTarget() == null) { creature = game.getPermanent(getTargetPointer().getFirst(game, source)); @@ -122,27 +142,23 @@ public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) } } if (creature == null) { - this.used = true; + this.discard(); return false; } - switch (layer) { - case TypeChangingEffects_4: - creature.addCardType(game, CardType.CREATURE); - creature.addSubType(game, SubType.SPIRIT); - break; - case AbilityAddingRemovingEffects_6: - creature.addAbility(FlyingAbility.getInstance(), source.getSourceId(), game); - break; - case PTChangingEffects_7: - if (sublayer == SubLayer.SetPT_7b) { - creature.getPower().setModifiedBaseValue(1); - creature.getToughness().setModifiedBaseValue(1); - } - break; - } + affectedObjects.add(creature); return true; } + @Override + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + List affectedObjects = new ArrayList<>(); + if (queryAffectedObjects(layer, source, game, affectedObjects)) { + applyToObjects(layer, sublayer, source, game, affectedObjects); + return true; + } + return false; + } + @Override public boolean hasLayer(Layer layer) { return layer == Layer.TypeChangingEffects_4 || diff --git a/Mage.Sets/src/mage/cards/a/ActOfAuthority.java b/Mage.Sets/src/mage/cards/a/ActOfAuthority.java index 87b9cebbdaea..6124c062494d 100644 --- a/Mage.Sets/src/mage/cards/a/ActOfAuthority.java +++ b/Mage.Sets/src/mage/cards/a/ActOfAuthority.java @@ -1,13 +1,13 @@ package mage.cards.a; -import java.util.UUID; +import mage.MageItem; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.ExileTargetEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; @@ -17,6 +17,9 @@ import mage.target.TargetPermanent; import mage.target.targetpointer.FixedTarget; +import java.util.List; +import java.util.UUID; + /** * * @author LevelX2 @@ -106,17 +109,22 @@ public ActOfAuthorityGainControlEffect copy() { } @Override - public boolean apply(Game game, Ability source) { - Permanent permanent; - permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + ((Permanent) object).changeControllerId(controller, game, source); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); if (permanent == null) { permanent = game.getPermanent(source.getFirstTarget()); } - if (permanent == null) { return false; } - - return permanent.changeControllerId(controller, game, source); + affectedObjects.add(permanent); + return true; } } diff --git a/Mage.Sets/src/mage/cards/a/AettirAndPriwen.java b/Mage.Sets/src/mage/cards/a/AettirAndPriwen.java index fa06d1f2ae8f..e7f22d19e3cf 100644 --- a/Mage.Sets/src/mage/cards/a/AettirAndPriwen.java +++ b/Mage.Sets/src/mage/cards/a/AettirAndPriwen.java @@ -1,5 +1,6 @@ package mage.cards.a; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousEffectImpl; @@ -7,12 +8,11 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; -import mage.game.Controllable; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; -import java.util.Optional; +import java.util.List; import java.util.UUID; /** @@ -60,23 +60,26 @@ public AettirAndPriwenEffect copy() { } @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = Optional - .ofNullable(source.getSourcePermanentIfItStillExists(game)) - .map(Permanent::getAttachedTo) - .map(game::getPermanent) - .orElse(null); - if (permanent == null) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + int life = game.getPlayer(source.getControllerId()).getLife(); + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; + permanent.getPower().setModifiedBaseValue(life); + permanent.getToughness().setModifiedBaseValue(life); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + Player player = game.getPlayer(source.getControllerId()); + if (player == null) { return false; } - Optional.ofNullable(source) - .map(Controllable::getControllerId) - .map(game::getPlayer) - .map(Player::getLife) - .ifPresent(life -> { - permanent.getPower().setModifiedBaseValue(life); - permanent.getToughness().setModifiedBaseValue(life); - }); - return true; + Permanent permanent = game.getPermanent(source.getSourceId()); + if (permanent != null) { + affectedObjects.add(permanent); + return true; + } + return false; } } diff --git a/Mage.Sets/src/mage/cards/a/AeveProgenitorOoze.java b/Mage.Sets/src/mage/cards/a/AeveProgenitorOoze.java index 64cd61c35a30..5efdc11d872a 100644 --- a/Mage.Sets/src/mage/cards/a/AeveProgenitorOoze.java +++ b/Mage.Sets/src/mage/cards/a/AeveProgenitorOoze.java @@ -1,6 +1,7 @@ package mage.cards.a; import mage.MageInt; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.common.SimpleStaticAbility; @@ -18,6 +19,7 @@ import mage.game.permanent.Permanent; import mage.game.permanent.PermanentToken; +import java.util.List; import java.util.UUID; /** @@ -79,10 +81,17 @@ public AeveProgenitorOozeNonLegendaryEffect copy() { } @Override - public boolean apply(Game game, Ability source) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + ((Permanent) object).removeSuperType(game, SuperType.LEGENDARY); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Permanent permanent = game.getPermanent(source.getSourceId()); if (permanent instanceof PermanentToken) { - permanent.removeSuperType(game, SuperType.LEGENDARY); + affectedObjects.add(permanent); return true; } return false; diff --git a/Mage.Sets/src/mage/cards/a/AgathasSoulCauldron.java b/Mage.Sets/src/mage/cards/a/AgathasSoulCauldron.java index 6486f78319cb..981fd6af0e1a 100644 --- a/Mage.Sets/src/mage/cards/a/AgathasSoulCauldron.java +++ b/Mage.Sets/src/mage/cards/a/AgathasSoulCauldron.java @@ -1,5 +1,6 @@ package mage.cards.a; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleStaticAbility; @@ -28,6 +29,7 @@ import mage.util.CardUtil; import java.util.Collection; +import java.util.List; import java.util.Set; import java.util.UUID; import java.util.stream.Collectors; @@ -119,7 +121,26 @@ private AgathasSoulCauldronAbilityEffect(final AgathasSoulCauldronAbilityEffect } @Override - public boolean apply(Game game, Ability source) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + ExileZone exileZone = game.getExile().getExileZone(CardUtil.getExileZoneId( + game, source.getSourceId(), game.getState().getZoneChangeCounter(source.getSourceId()) + )); + Set abilities = exileZone + .getCards(StaticFilters.FILTER_CARD_CREATURE, game) + .stream() + .map(card -> card.getAbilities(game)) + .flatMap(Collection::stream) + .filter(Ability::isActivatedAbility) + .collect(Collectors.toSet()); + for (MageItem object : affectedObjects) { + for (Ability ability : abilities) { + ((Permanent) object).addAbility(ability, source.getSourceId(), game, true); + } + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { ExileZone exileZone = game.getExile().getExileZone(CardUtil.getExileZoneId( game, source.getSourceId(), game.getState().getZoneChangeCounter(source.getSourceId()) )); @@ -136,12 +157,8 @@ public boolean apply(Game game, Ability source) { if (abilities.isEmpty()) { return false; } - for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game)) { - for (Ability ability : abilities) { - permanent.addAbility(ability, source.getSourceId(), game, true); - } - } - return true; + affectedObjects.addAll(game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game)); + return !affectedObjects.isEmpty(); } @Override diff --git a/Mage.Sets/src/mage/cards/a/AgelessSentinels.java b/Mage.Sets/src/mage/cards/a/AgelessSentinels.java index a345aff257aa..5f8f3c742adb 100644 --- a/Mage.Sets/src/mage/cards/a/AgelessSentinels.java +++ b/Mage.Sets/src/mage/cards/a/AgelessSentinels.java @@ -3,16 +3,16 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.BlocksSourceTriggeredAbility; -import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.Effect; +import mage.abilities.effects.common.continuous.AddCardSubTypeSourceEffect; import mage.abilities.effects.common.continuous.LoseAbilitySourceEffect; import mage.abilities.keyword.DefenderAbility; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; -import mage.game.Game; -import mage.game.permanent.Permanent; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; import java.util.UUID; @@ -35,7 +35,8 @@ public AgelessSentinels(UUID ownerId, CardSetInfo setInfo) { this.addAbility(FlyingAbility.getInstance()); // When Ageless Sentinels blocks, it becomes a Bird Giant, and it loses defender. - Ability ability = new BlocksSourceTriggeredAbility(new AgelessSentinelsEffect()).setTriggerPhrase("When {this} blocks, "); + Effect becomeBirdGiantEffect = new AddCardSubTypeSourceEffect(Duration.WhileOnBattlefield, SubType.BIRD, SubType.GIANT); + Ability ability = new BlocksSourceTriggeredAbility(becomeBirdGiantEffect).setTriggerPhrase("When {this} blocks, "); Effect effect = new LoseAbilitySourceEffect(DefenderAbility.getInstance(), Duration.WhileOnBattlefield); effect.setText(", and it loses defender. (It's no longer a Wall. This effect lasts indefinitely.)"); ability.addEffect(effect); @@ -51,36 +52,3 @@ public AgelessSentinels copy() { return new AgelessSentinels(this); } } - -class AgelessSentinelsEffect extends ContinuousEffectImpl { - - AgelessSentinelsEffect() { - super(Duration.WhileOnBattlefield, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.BecomeCreature); - staticText = "it becomes a Bird Giant"; - } - - private AgelessSentinelsEffect(final AgelessSentinelsEffect effect) { - super(effect); - } - - @Override - public AgelessSentinelsEffect copy() { - return new AgelessSentinelsEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent == null) { - return false; - } - permanent.removeAllCreatureTypes(game); - permanent.addSubType(game, SubType.BIRD, SubType.GIANT); - return true; - } - - @Override - public boolean hasLayer(Layer layer) { - return layer == Layer.TypeChangingEffects_4; - } -} diff --git a/Mage.Sets/src/mage/cards/a/AkroanHorse.java b/Mage.Sets/src/mage/cards/a/AkroanHorse.java index 40127944a071..fb75dd072126 100644 --- a/Mage.Sets/src/mage/cards/a/AkroanHorse.java +++ b/Mage.Sets/src/mage/cards/a/AkroanHorse.java @@ -1,6 +1,7 @@ package mage.cards.a; import mage.MageInt; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; @@ -20,6 +21,7 @@ import mage.target.common.TargetOpponent; import mage.target.targetpointer.FixedTarget; +import java.util.List; import java.util.UUID; /** @@ -110,7 +112,14 @@ public AkroanHorseGainControlEffect copy() { } @Override - public boolean apply(Game game, Ability source) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + ((Permanent) object).changeControllerId(controller, game, source); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); if (permanent == null) { permanent = game.getPermanent(source.getFirstTarget()); @@ -118,6 +127,7 @@ public boolean apply(Game game, Ability source) { if (permanent == null) { return false; } - return permanent.changeControllerId(controller, game, source); + affectedObjects.add(permanent); + return true; } } diff --git a/Mage.Sets/src/mage/cards/a/AlpineMoon.java b/Mage.Sets/src/mage/cards/a/AlpineMoon.java index da13a2bff440..145bba65dbf8 100644 --- a/Mage.Sets/src/mage/cards/a/AlpineMoon.java +++ b/Mage.Sets/src/mage/cards/a/AlpineMoon.java @@ -1,5 +1,7 @@ package mage.cards.a; +import mage.MageItem; +import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.SimpleStaticAbility; @@ -16,6 +18,8 @@ import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.ArrayList; +import java.util.List; import java.util.UUID; /** @@ -69,32 +73,55 @@ public AlpineMoonEffect copy() { } @Override - public boolean apply(Game game, Ability source) { - return false; - } - - @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - String cardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY); - if (cardName == null) { - return false; - } - FilterPermanent filter2 = filter.copy(); - filter2.add(new NamePredicate(cardName)); - for (Permanent land : game.getBattlefield().getActivePermanents(filter2, source.getControllerId(), game)) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent land = (Permanent) object; 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.removeAllAbilities(source.getSourceId(), game); land.removeAllSubTypes(game, SubTypeSet.NonBasicLandType); + land.removeAllSubTypes(game, SubTypeSet.BasicLandType); break; case AbilityAddingRemovingEffects_6: + land.removeAllAbilities(source.getSourceId(), game); land.addAbility(new AnyColorManaAbility(), source.getSourceId(), game); break; } } - return true; + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + if (layer == Layer.TypeChangingEffects_4) { + affectedObjectList.clear(); + String cardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY); + if (cardName == null) { + return false; + } + FilterPermanent filter2 = filter.copy(); + filter2.add(new NamePredicate(cardName)); + for (Permanent permanent : game.getBattlefield().getActivePermanents(filter2, source.getControllerId(), game)) { + affectedObjects.add(permanent); + affectedObjectList.add(new MageObjectReference(permanent, game)); + } + } else { + for (MageObjectReference mor : affectedObjectList) { + Permanent permanent = mor.getPermanent(game); + if (permanent != null) { + affectedObjects.add(permanent); + } + } + } + return !affectedObjects.isEmpty(); + } + + @Override + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + ArrayList affectedObjects = new ArrayList<>(); + if (queryAffectedObjects(layer, source, game, affectedObjects)) { + applyToObjects(layer, sublayer, source, game, affectedObjects); + return true; + } + return false; } @Override diff --git a/Mage.Sets/src/mage/cards/a/Aluren.java b/Mage.Sets/src/mage/cards/a/Aluren.java index 716287acfd93..6ba5d7a61b1c 100644 --- a/Mage.Sets/src/mage/cards/a/Aluren.java +++ b/Mage.Sets/src/mage/cards/a/Aluren.java @@ -1,6 +1,7 @@ package mage.cards.a; import mage.MageIdentifier; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.SourceIsSpellCondition; @@ -16,6 +17,7 @@ import mage.game.Game; import mage.players.Player; +import java.util.List; import java.util.UUID; /** @@ -92,19 +94,27 @@ public AlurenRuleEffect copy() { } @Override - public boolean apply(Game game, Ability source) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + alternativeCastingCostAbility.setSourceId(source.getControllerId()); + for (MageItem object : affectedObjects) { + Player player = (Player) object; + player.getAlternativeSourceCosts().add(alternativeCastingCostAbility); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Player controller = game.getPlayer(source.getControllerId()); if (controller == null) { return false; } - alternativeCastingCostAbility.setSourceId(source.getSourceId()); for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { Player player = game.getPlayer(playerId); if (player != null) { - player.getAlternativeSourceCosts().add(alternativeCastingCostAbility); + affectedObjects.add(player); } } - return true; + return !affectedObjects.isEmpty(); } } \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/a/AnHavvaConstable.java b/Mage.Sets/src/mage/cards/a/AnHavvaConstable.java index f077d7390411..755a0e2c8007 100644 --- a/Mage.Sets/src/mage/cards/a/AnHavvaConstable.java +++ b/Mage.Sets/src/mage/cards/a/AnHavvaConstable.java @@ -1,20 +1,21 @@ package mage.cards.a; -import java.util.UUID; import mage.MageInt; -import mage.MageObject; import mage.ObjectColor; -import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.IntPlusDynamicValue; +import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.effects.common.continuous.SetBaseToughnessSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.ColorPredicate; -import mage.game.Game; -import mage.players.Player; + +import java.util.UUID; /** * @@ -22,6 +23,13 @@ */ public final class AnHavvaConstable extends CardImpl { + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("green creatures"); + private static final DynamicValue creatureValue = new IntPlusDynamicValue(1, new PermanentsOnBattlefieldCount(filter)); + + static { + filter.add(new ColorPredicate(ObjectColor.GREEN)); + } + public AnHavvaConstable(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{G}{G}"); this.subtype.add(SubType.HUMAN); @@ -29,7 +37,8 @@ public AnHavvaConstable(UUID ownerId, CardSetInfo setInfo) { this.toughness = new MageInt(1); // An-Havva Constable's toughness is equal to 1 plus the number of green creatures on the battlefield. - this.addAbility(new SimpleStaticAbility(new AnHavvaConstableEffect())); + this.addAbility(new SimpleStaticAbility(new SetBaseToughnessSourceEffect(creatureValue) + .setText("An-Havva Constable's toughness is equal to 1 plus the number of green creatures on the battlefield"))); } private AnHavvaConstable(final AnHavvaConstable card) { @@ -41,41 +50,3 @@ public AnHavvaConstable copy() { return new AnHavvaConstable(this); } } - -class AnHavvaConstableEffect extends ContinuousEffectImpl { - - AnHavvaConstableEffect() { - super(Duration.WhileOnBattlefield, Layer.PTChangingEffects_7, SubLayer.CharacteristicDefining_7a, Outcome.BoostCreature); - staticText = "{this}'s toughness is equal to 1 plus the number of green creatures on the battlefield"; - } - - private AnHavvaConstableEffect(final AnHavvaConstableEffect effect) { - super(effect); - } - - @Override - public AnHavvaConstableEffect copy() { - return new AnHavvaConstableEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller == null) { - return false; - } - - MageObject mageObject = game.getObject(source.getSourceId()); - if (mageObject == null) { - return false; - } - - FilterCreaturePermanent filter = new FilterCreaturePermanent("green creatures"); - filter.add(new ColorPredicate(ObjectColor.GREEN)); - int numberOfGreenCreatures = game.getBattlefield().count(filter, source.getSourceId(), source, game); - - mageObject.getToughness().setModifiedBaseValue(1 + numberOfGreenCreatures); - - return true; - } -} diff --git a/Mage.Sets/src/mage/cards/a/AngelOfJubilation.java b/Mage.Sets/src/mage/cards/a/AngelOfJubilation.java index 535752c85f45..57f73f0e040e 100644 --- a/Mage.Sets/src/mage/cards/a/AngelOfJubilation.java +++ b/Mage.Sets/src/mage/cards/a/AngelOfJubilation.java @@ -1,6 +1,7 @@ package mage.cards.a; import mage.MageInt; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.Cost; @@ -19,6 +20,7 @@ import mage.game.Game; import mage.players.Player; +import java.util.List; import java.util.UUID; /** @@ -71,13 +73,21 @@ public AngelOfJubilationEffect copy() { } @Override - public boolean apply(Game game, Ability source) { - for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) { - Player player = game.getPlayer(playerId); + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Player player = (Player) object; player.setPayLifeCostLevel(Player.PayLifeCostLevel.nonSpellnonActivatedAbilities); player.setCanPaySacrificeCostFilter(new FilterCreaturePermanent()); } - return true; + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) { + Player player = game.getPlayer(playerId); + affectedObjects.add(player); + } + return !affectedObjects.isEmpty(); } } diff --git a/Mage.Sets/src/mage/cards/a/AnheloThePainter.java b/Mage.Sets/src/mage/cards/a/AnheloThePainter.java index caf60af58cde..bffebd3ba3f3 100644 --- a/Mage.Sets/src/mage/cards/a/AnheloThePainter.java +++ b/Mage.Sets/src/mage/cards/a/AnheloThePainter.java @@ -1,6 +1,7 @@ package mage.cards.a; import mage.MageInt; +import mage.MageItem; import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; @@ -19,6 +20,7 @@ import mage.watchers.Watcher; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.UUID; @@ -69,6 +71,35 @@ private AnheloThePainterGainCausalityEffect(final AnheloThePainterGainCausalityE super(effect); } + @Override + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Card card = (Card) object; + game.getState().addOtherAbility(card, new CasualtyAbility(2)); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + Player controller = game.getPlayer(source.getControllerId()); + AnheloThePainterWatcher watcher = game.getState().getWatcher(AnheloThePainterWatcher.class); + if (controller == null || watcher == null) { + return false; + } + + for (StackObject stackObject : game.getStack()) { + if (!(stackObject instanceof Spell) + || stackObject.isCopy() + || !stackObject.isControlledBy(source.getControllerId()) + || !AnheloThePainterWatcher.checkSpell(stackObject, game)) { + continue; + } + Card card = ((Spell) stackObject).getCard(); + affectedObjects.add(card); + } + return !affectedObjects.isEmpty(); + } + @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); diff --git a/Mage.Sets/src/mage/cards/a/AnimateArtifact.java b/Mage.Sets/src/mage/cards/a/AnimateArtifact.java index 3b40eec226e6..785328344703 100644 --- a/Mage.Sets/src/mage/cards/a/AnimateArtifact.java +++ b/Mage.Sets/src/mage/cards/a/AnimateArtifact.java @@ -1,7 +1,7 @@ package mage.cards.a; -import java.util.UUID; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousEffectImpl; @@ -18,6 +18,10 @@ import mage.target.TargetPermanent; import mage.target.common.TargetArtifactPermanent; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + /** * * @author MTGfan @@ -57,6 +61,8 @@ public AnimateArtifact copy() { class AnimateArtifactContinuousEffect extends ContinuousEffectImpl { + private boolean addedCreatureType = false; + AnimateArtifactContinuousEffect(Duration duration) { super(duration, Outcome.Benefit); staticText = "As long as enchanted artifact isn't a creature, it's an artifact creature with power and toughness each equal to its mana value"; @@ -64,6 +70,7 @@ class AnimateArtifactContinuousEffect extends ContinuousEffectImpl { private AnimateArtifactContinuousEffect(final AnimateArtifactContinuousEffect effect) { super(effect); + this.addedCreatureType = effect.addedCreatureType; } @Override @@ -72,34 +79,53 @@ public AnimateArtifactContinuousEffect copy() { } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - // Not sure, if this is layerwise handled absolutely correctly + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; + switch (layer) { + case TypeChangingEffects_4: + permanent.addCardType(game, CardType.CREATURE); + this.addedCreatureType = true; + break; + case PTChangingEffects_7: + if (sublayer != SubLayer.SetPT_7b) { + continue; + } + permanent.getPower().setModifiedBaseValue(permanent.getManaValue()); + permanent.getToughness().setModifiedBaseValue(permanent.getManaValue()); + this.addedCreatureType = false; + } + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Permanent enchantment = game.getPermanent(source.getSourceId()); if (enchantment == null) { return false; } Permanent permanent = game.getPermanent(enchantment.getAttachedTo()); - if (permanent == null || permanent.isCreature(game)) { - return false; - } - if (sublayer != SubLayer.NA) { + if (permanent == null || (permanent.isCreature(game) && !this.addedCreatureType)) { return false; } - - permanent.addCardType(game, CardType.CREATURE); - permanent.getPower().setModifiedBaseValue(permanent.getManaValue()); - permanent.getToughness().setModifiedBaseValue(permanent.getManaValue()); + affectedObjects.add(permanent); return true; } @Override - public boolean apply(Game game, Ability source) { + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + List affectedObjects = new ArrayList<>(); + if (queryAffectedObjects(layer, source, game, affectedObjects)) { + applyToObjects(layer, sublayer, source, game, affectedObjects); + return true; + } return false; } @Override public boolean hasLayer(Layer layer) { - return layer == Layer.TypeChangingEffects_4; + return layer == Layer.TypeChangingEffects_4 || + layer == Layer.PTChangingEffects_7; } } diff --git a/Mage.Sets/src/mage/cards/a/AquitectsWill.java b/Mage.Sets/src/mage/cards/a/AquitectsWill.java index e7e96b903be4..8b2fc9f2e2e2 100644 --- a/Mage.Sets/src/mage/cards/a/AquitectsWill.java +++ b/Mage.Sets/src/mage/cards/a/AquitectsWill.java @@ -1,5 +1,6 @@ package mage.cards.a; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; @@ -9,13 +10,17 @@ import mage.abilities.effects.common.counter.AddCountersTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Layer; +import mage.constants.SubType; import mage.counters.CounterType; import mage.filter.common.FilterControlledPermanent; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.common.TargetLandPermanent; +import java.util.List; import java.util.UUID; /** @@ -71,12 +76,13 @@ public AquitectsWillEffect copy() { } @Override - public boolean apply(Game game, Ability source) { + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Permanent land = game.getPermanent(this.getTargetPointer().getFirst(game, source)); if (land == null || land.getCounters(game).getCount(CounterType.FLOOD) < 1) { discard(); return false; } - return super.apply(game, source); + affectedObjects.add(land); + return true; } } diff --git a/Mage.Sets/src/mage/cards/a/AraumiOfTheDeadTide.java b/Mage.Sets/src/mage/cards/a/AraumiOfTheDeadTide.java index 271610b34ae1..9c68330c5c6c 100644 --- a/Mage.Sets/src/mage/cards/a/AraumiOfTheDeadTide.java +++ b/Mage.Sets/src/mage/cards/a/AraumiOfTheDeadTide.java @@ -1,6 +1,7 @@ package mage.cards.a; import mage.MageInt; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.Cost; @@ -16,6 +17,7 @@ import mage.target.TargetCard; import mage.target.common.TargetCardInYourGraveyard; +import java.util.List; import java.util.UUID; /** @@ -67,12 +69,20 @@ public AraumiOfTheDeadTideEffect copy() { } @Override - public boolean apply(Game game, Ability source) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Card card = (Card) object; + game.getState().addOtherAbility(card, new EncoreAbility(card.getManaCost())); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Card card = game.getCard(getTargetPointer().getFirst(game, source)); if (card == null) { return false; } - game.getState().addOtherAbility(card, new EncoreAbility(card.getManaCost())); + affectedObjects.add(card); return true; } } diff --git a/Mage.Sets/src/mage/cards/a/ArcheryTraining.java b/Mage.Sets/src/mage/cards/a/ArcheryTraining.java index 830389f78c2c..4c2d3c13ef4a 100644 --- a/Mage.Sets/src/mage/cards/a/ArcheryTraining.java +++ b/Mage.Sets/src/mage/cards/a/ArcheryTraining.java @@ -1,5 +1,6 @@ package mage.cards.a; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; @@ -22,6 +23,7 @@ import mage.target.common.TargetAttackingOrBlockingCreature; import mage.target.common.TargetCreaturePermanent; +import java.util.List; import java.util.UUID; /** @@ -78,7 +80,22 @@ public ArcheryTrainingEffect copy() { } @Override - public boolean apply(Game game, Ability source) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + Permanent aura = game.getPermanent(source.getSourceId()); + for (MageItem object : affectedObjects) { + Permanent permanent = game.getPermanent(object.getId()); + String rule = "this creature deals X damage to target attacking or blocking creature, " + + "where X is the number of arrow counters on " + aura.getName(); + Ability ability = new SimpleActivatedAbility( + new DamageTargetEffect(new ArcheryTrainingValue(aura)).setText(rule), new TapSourceCost() + ); + ability.addTarget(new TargetAttackingOrBlockingCreature()); + permanent.addAbility(ability, source.getSourceId(), game); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Permanent aura = game.getPermanent(source.getSourceId()); if (aura == null) { return false; @@ -87,13 +104,7 @@ public boolean apply(Game game, Ability source) { if (permanent == null) { return false; } - String rule = "this creature deals X damage to target attacking or blocking creature, " + - "where X is the number of arrow counters on " + aura.getName(); - Ability ability = new SimpleActivatedAbility( - new DamageTargetEffect(new ArcheryTrainingValue(aura)).setText(rule), new TapSourceCost() - ); - ability.addTarget(new TargetAttackingOrBlockingCreature()); - permanent.addAbility(ability, source.getSourceId(), game); + affectedObjects.add(permanent); return true; } } diff --git a/Mage.Sets/src/mage/cards/a/ArchmagesNewt.java b/Mage.Sets/src/mage/cards/a/ArchmagesNewt.java index 43d294c2e732..0eb553ab06be 100644 --- a/Mage.Sets/src/mage/cards/a/ArchmagesNewt.java +++ b/Mage.Sets/src/mage/cards/a/ArchmagesNewt.java @@ -1,6 +1,7 @@ package mage.cards.a; import mage.MageInt; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; import mage.abilities.condition.common.SaddledCondition; @@ -16,6 +17,7 @@ import mage.game.Game; import mage.target.common.TargetCardInYourGraveyard; +import java.util.List; import java.util.UUID; /** @@ -77,20 +79,30 @@ public void init(Ability source, Game game) { } @Override - public boolean apply(Game game, Ability source) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Card card = (Card) object; + + FlashbackAbility ability; + if (saddled) { + ability = new FlashbackAbility(card, new GenericManaCost(0)); + } else { + ability = new FlashbackAbility(card, card.getManaCost()); + } + ability.setSourceId(card.getId()); + ability.setControllerId(card.getOwnerId()); + + game.getState().addOtherAbility(card, ability); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Card card = game.getCard(getTargetPointer().getFirst(game, source)); if (card == null) { return false; } - FlashbackAbility ability; - if (saddled) { - ability = new FlashbackAbility(card, new GenericManaCost(0)); - } else { - ability = new FlashbackAbility(card, card.getManaCost()); - } - ability.setSourceId(card.getId()); - ability.setControllerId(card.getOwnerId()); - game.getState().addOtherAbility(card, ability); + affectedObjects.add(card); return true; } } diff --git a/Mage.Sets/src/mage/cards/a/ArixmethesSlumberingIsle.java b/Mage.Sets/src/mage/cards/a/ArixmethesSlumberingIsle.java index 291e5a65642c..d9d3bb48a57c 100644 --- a/Mage.Sets/src/mage/cards/a/ArixmethesSlumberingIsle.java +++ b/Mage.Sets/src/mage/cards/a/ArixmethesSlumberingIsle.java @@ -1,6 +1,7 @@ package mage.cards.a; import mage.MageInt; +import mage.MageItem; import mage.Mana; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldAbility; @@ -22,6 +23,7 @@ import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.List; import java.util.UUID; /** @@ -87,14 +89,22 @@ public ArixmethesIsLandEffect copy() { } @Override - public boolean apply(Game game, Ability source) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; + permanent.removeAllCardTypes(game); + permanent.addCardType(game, CardType.LAND); + permanent.removeAllSubTypes(game); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Permanent permanent = game.getPermanent(source.getSourceId()); if (permanent == null) { return false; } - permanent.removeAllCardTypes(game); - permanent.addCardType(game, CardType.LAND); - permanent.removeAllSubTypes(game); + affectedObjects.add(permanent); return true; } } diff --git a/Mage.Sets/src/mage/cards/a/ArlinnTheMoonsFury.java b/Mage.Sets/src/mage/cards/a/ArlinnTheMoonsFury.java index bc906251947d..24d5c1851214 100644 --- a/Mage.Sets/src/mage/cards/a/ArlinnTheMoonsFury.java +++ b/Mage.Sets/src/mage/cards/a/ArlinnTheMoonsFury.java @@ -1,9 +1,8 @@ package mage.cards.a; import mage.Mana; -import mage.abilities.Ability; import mage.abilities.LoyaltyAbility; -import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect; import mage.abilities.effects.mana.BasicManaEffect; import mage.abilities.keyword.HasteAbility; import mage.abilities.keyword.IndestructibleAbility; @@ -11,9 +10,11 @@ import mage.abilities.keyword.TrampleAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; -import mage.game.Game; -import mage.game.permanent.Permanent; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.game.permanent.token.custom.CreatureToken; import java.util.UUID; @@ -41,7 +42,15 @@ public ArlinnTheMoonsFury(UUID ownerId, CardSetInfo setInfo) { )), 2)); // 0: Until end of turn, Arlinn, the Moon's Fury becomes a 5/5 Werewolf creature with trample, indestructible, and haste. - this.addAbility(new LoyaltyAbility(new ArlinnTheMoonsFuryEffect(), 0)); + this.addAbility(new LoyaltyAbility(new BecomesCreatureSourceEffect( + new CreatureToken(5, 5, "5/5 Werewolf creature with trample, indestructible, and haste") + .withSubType(SubType.WEREWOLF) + .withAbility(TrampleAbility.getInstance()) + .withAbility(IndestructibleAbility.getInstance()) + .withAbility(HasteAbility.getInstance()), + null, + Duration.EndOfTurn) + .withDurationRuleAtStart(true), 0)); } private ArlinnTheMoonsFury(final ArlinnTheMoonsFury card) { @@ -53,66 +62,3 @@ public ArlinnTheMoonsFury copy() { return new ArlinnTheMoonsFury(this); } } - -class ArlinnTheMoonsFuryEffect extends ContinuousEffectImpl { - - ArlinnTheMoonsFuryEffect() { - super(Duration.EndOfTurn, Outcome.Benefit); - staticText = "until end of turn, {this} becomes a 5/5 Werewolf creature with trample, indestructible, and haste"; - this.dependencyTypes.add(DependencyType.BecomeCreature); - } - - private ArlinnTheMoonsFuryEffect(final ArlinnTheMoonsFuryEffect effect) { - super(effect); - } - - @Override - public ArlinnTheMoonsFuryEffect copy() { - return new ArlinnTheMoonsFuryEffect(this); - } - - @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - Permanent permanent = source.getSourcePermanentIfItStillExists(game); - if (permanent == null) { - discard(); - return false; - } - switch (layer) { - case TypeChangingEffects_4: - permanent.removeAllCardTypes(game); - permanent.addCardType(game, CardType.CREATURE); - permanent.removeAllCreatureTypes(game); - permanent.addSubType(game, SubType.WEREWOLF); - return true; - case AbilityAddingRemovingEffects_6: - permanent.addAbility(TrampleAbility.getInstance(), source.getSourceId(), game); - permanent.addAbility(IndestructibleAbility.getInstance(), source.getSourceId(), game); - permanent.addAbility(HasteAbility.getInstance(), source.getSourceId(), game); - return true; - case PTChangingEffects_7: - if (sublayer == SubLayer.SetPT_7b) { - permanent.getPower().setModifiedBaseValue(5); - permanent.getToughness().setModifiedBaseValue(5); - return true; - } - } - return false; - } - - @Override - public boolean apply(Game game, Ability source) { - return false; - } - - @Override - public boolean hasLayer(Layer layer) { - switch (layer) { - case TypeChangingEffects_4: - case AbilityAddingRemovingEffects_6: - case PTChangingEffects_7: - return true; - } - return false; - } -} diff --git a/Mage.Sets/src/mage/cards/a/ArmamentMaster.java b/Mage.Sets/src/mage/cards/a/ArmamentMaster.java index 46591b108a75..e825de54829f 100644 --- a/Mage.Sets/src/mage/cards/a/ArmamentMaster.java +++ b/Mage.Sets/src/mage/cards/a/ArmamentMaster.java @@ -2,12 +2,14 @@ package mage.cards.a; import mage.MageInt; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousEffectImpl; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; +import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.game.permanent.Permanent; @@ -50,7 +52,7 @@ public ArmamentMaster copy() { class ArmamentMasterEffect extends ContinuousEffectImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Other Kor creatures you control"); + private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("Other Kor creatures you control"); static { filter.add(SubType.KOR.getPredicate()); @@ -71,16 +73,23 @@ public ArmamentMasterEffect copy() { } @Override - public boolean apply(Game game, Ability source) { - int count = countEquipment(game, source); - List permanents = game.getBattlefield().getAllActivePermanents(filter, source.getControllerId(), game); - for (Permanent perm : permanents) { - if (!perm.getId().equals(source.getSourceId())) { - perm.addPower(2 * count); - perm.addToughness(2 * count); - } + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + int equipmentCount = countEquipment(game, source); + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; + permanent.addPower(2 * equipmentCount); + permanent.addToughness(2 * equipmentCount); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + int equipmentCount = countEquipment(game, source); + if (equipmentCount < 1) { + return false; } - return true; + affectedObjects.addAll(game.getBattlefield().getActivePermanents(filter, source.getControllerId(), game)); + return !affectedObjects.isEmpty(); } private int countEquipment(Game game, Ability source) { diff --git a/Mage.Sets/src/mage/cards/a/ArmedWithProof.java b/Mage.Sets/src/mage/cards/a/ArmedWithProof.java index ab20f6525916..5b1c4f03ee14 100644 --- a/Mage.Sets/src/mage/cards/a/ArmedWithProof.java +++ b/Mage.Sets/src/mage/cards/a/ArmedWithProof.java @@ -1,5 +1,6 @@ package mage.cards.a; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; @@ -15,6 +16,8 @@ import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.ArrayList; +import java.util.List; import java.util.UUID; /** @@ -62,10 +65,9 @@ public ArmedWithProofEffect copy() { } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - for (Permanent permanent : game.getBattlefield().getActivePermanents( - filter, source.getControllerId(), source, game - )) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; switch (layer) { case TypeChangingEffects_4: permanent.addSubType(game, SubType.EQUIPMENT); @@ -78,11 +80,21 @@ public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) break; } } - return true; } @Override - public boolean apply(Game game, Ability source) { + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + affectedObjects.addAll(game.getBattlefield().getActivePermanents(filter, source.getControllerId(), game)); + return !affectedObjects.isEmpty(); + } + + @Override + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + List affectedObjects = new ArrayList<>(); + if (queryAffectedObjects(layer, source, game, affectedObjects)) { + applyToObjects(layer, sublayer, source, game, affectedObjects); + return true; + } return false; } diff --git a/Mage.Sets/src/mage/cards/a/ArterialAlchemy.java b/Mage.Sets/src/mage/cards/a/ArterialAlchemy.java index 0750354b54e4..57ec323b18a7 100644 --- a/Mage.Sets/src/mage/cards/a/ArterialAlchemy.java +++ b/Mage.Sets/src/mage/cards/a/ArterialAlchemy.java @@ -1,5 +1,6 @@ package mage.cards.a; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; @@ -18,6 +19,8 @@ import mage.game.permanent.Permanent; import mage.game.permanent.token.BloodToken; +import java.util.ArrayList; +import java.util.List; import java.util.UUID; /** @@ -72,10 +75,9 @@ public ArterialAlchemyEffect copy() { } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - for (Permanent permanent : game.getBattlefield().getActivePermanents( - filter, source.getControllerId(), source, game - )) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; switch (layer) { case TypeChangingEffects_4: permanent.addSubType(game, SubType.EQUIPMENT); @@ -88,11 +90,21 @@ public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) break; } } - return true; } @Override - public boolean apply(Game game, Ability source) { + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + affectedObjects.addAll(game.getBattlefield().getActivePermanents(filter, source.getControllerId(), game)); + return !affectedObjects.isEmpty(); + } + + @Override + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + List affectedObjects = new ArrayList<>(); + if (queryAffectedObjects(layer, source, game, affectedObjects)) { + applyToObjects(layer, sublayer, source, game, affectedObjects); + return true; + } return false; } diff --git a/Mage.Sets/src/mage/cards/a/AsForetold.java b/Mage.Sets/src/mage/cards/a/AsForetold.java index f5a67dc386cf..9bddd6e1e704 100644 --- a/Mage.Sets/src/mage/cards/a/AsForetold.java +++ b/Mage.Sets/src/mage/cards/a/AsForetold.java @@ -1,5 +1,6 @@ package mage.cards.a; +import mage.MageItem; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.SpellAbility; @@ -19,6 +20,8 @@ import mage.game.permanent.Permanent; import mage.players.Player; +import java.util.ArrayList; +import java.util.List; import java.util.UUID; /** @@ -133,31 +136,46 @@ public AsForetoldAddAltCostEffect copy() { } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - Permanent sourcePermanent = game.getPermanent(source.getSourceId()); - if (sourcePermanent != null) { - Boolean wasItUsed = (Boolean) game.getState().getValue( - sourcePermanent.getId().toString() - + sourcePermanent.getZoneChangeCounter(game) - + sourcePermanent.getTurnsOnBattlefield()); - // If we haven't used it yet this turn, give the option of using the zero alternative cost - if (wasItUsed == null) { - int timeCounters = sourcePermanent.getCounters(game).getCount(CounterType.TIME); - AsForetoldAlternativeCost alternateCostAbility = new AsForetoldAlternativeCost(timeCounters); - alternateCostAbility.setSourceId(source.getSourceId()); - controller.getAlternativeSourceCosts().add(alternateCostAbility); - } - // Return true even if we didn't add the alt cost. We still applied the effect - return true; + for (MageItem object : affectedObjects) { + Permanent sourcePermanent = (Permanent) object; + Boolean wasItUsed = (Boolean) game.getState().getValue( + sourcePermanent.getId().toString() + + sourcePermanent.getZoneChangeCounter(game) + + sourcePermanent.getTurnsOnBattlefield()); + // If we haven't used it yet this turn, give the option of using the zero alternative cost + if (wasItUsed == null) { + int timeCounters = sourcePermanent.getCounters(game).getCount(CounterType.TIME); + AsForetoldAlternativeCost alternateCostAbility = new AsForetoldAlternativeCost(timeCounters); + alternateCostAbility.setSourceId(source.getSourceId()); + controller.getAlternativeSourceCosts().add(alternateCostAbility); } } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return false; + } + Permanent permanent = game.getPermanent(source.getSourceId()); + if (permanent != null) { + affectedObjects.add(permanent); + return true; + } return false; } @Override - public boolean apply(Game game, Ability source) { + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + List affectedObjects = new ArrayList<>(); + if (queryAffectedObjects(layer, source, game, affectedObjects)) { + applyToObjects(layer, sublayer, source, game, affectedObjects); + // Return true even if we didn't add the alt cost. We still applied the effect + return true; + } return false; } diff --git a/Mage.Sets/src/mage/cards/a/AshayaSoulOfTheWild.java b/Mage.Sets/src/mage/cards/a/AshayaSoulOfTheWild.java index 8f726adaa2a2..30a6bd0ea7e5 100644 --- a/Mage.Sets/src/mage/cards/a/AshayaSoulOfTheWild.java +++ b/Mage.Sets/src/mage/cards/a/AshayaSoulOfTheWild.java @@ -1,6 +1,7 @@ package mage.cards.a; import mage.MageInt; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.dynamicvalue.common.LandsYouControlCount; @@ -16,6 +17,7 @@ import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.List; import java.util.UUID; /** @@ -76,11 +78,10 @@ public AshayaSoulOfTheWildEffect copy() { } @Override - public boolean apply(Game game, Ability source) { - for (Permanent permanent : game.getBattlefield().getActivePermanents( - filter, source.getControllerId(), source, game - )) { - if (!permanent.isLand(game)) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; + if (!permanent.isLand()) { permanent.addCardType(game, CardType.LAND); } permanent.addSubType(game, SubType.FOREST); @@ -88,6 +89,11 @@ public boolean apply(Game game, Ability source) { permanent.addAbility(new GreenManaAbility(), source.getSourceId(), game); } } - return true; + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + affectedObjects.addAll(game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game)); + return !affectedObjects.isEmpty(); } } diff --git a/Mage.Sets/src/mage/cards/a/AshesOfTheFallen.java b/Mage.Sets/src/mage/cards/a/AshesOfTheFallen.java index 7d66823818e1..0842c3462ee6 100644 --- a/Mage.Sets/src/mage/cards/a/AshesOfTheFallen.java +++ b/Mage.Sets/src/mage/cards/a/AshesOfTheFallen.java @@ -1,6 +1,6 @@ package mage.cards.a; -import mage.MageObject; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.SimpleStaticAbility; @@ -10,11 +10,12 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; +import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; -import mage.util.CardUtil; +import java.util.List; import java.util.UUID; /** @@ -55,31 +56,30 @@ private AshesOfTheFallenEffect(final AshesOfTheFallenEffect effect) { } @Override - public boolean apply(Game game, Ability source) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + Permanent permanent = game.getPermanent(source.getSourceId()); + SubType subType = ChooseCreatureTypeEffect.getChosenCreatureType(permanent.getId(), game); + for (MageItem object : affectedObjects) { + Card card = (Card) object; + card.addSubType(game, subType); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Player controller = game.getPlayer(source.getControllerId()); Permanent permanent = game.getPermanent(source.getSourceId()); - if (controller != null && permanent != null) { - SubType subType = ChooseCreatureTypeEffect.getChosenCreatureType(permanent.getId(), game); - if (subType != null) { - for (UUID cardId : controller.getGraveyard()) { - Card card = game.getCard(cardId); - if (card != null && card.isCreature(game) && !card.hasSubtype(subType, game)) { - MageObject mageObject = game.getObject(card.getId()); - if (mageObject != null) { - CardUtil.getObjectPartsAsObjects(mageObject).forEach(objectPart ->{ - if (objectPart.isCreature(game)) { - game.getState().getCreateMageObjectAttribute(objectPart, game).getSubtype().add(subType); - } - }); - } - } - } - } else { - discard(); + if (controller == null || permanent == null) { + return false; + } + SubType subType = ChooseCreatureTypeEffect.getChosenCreatureType(permanent.getId(), game); + for (Card card : controller.getGraveyard().getCards(StaticFilters.FILTER_CARD_CREATURE, game)) { + if (!card.hasSubtype(subType, game)) { + continue; } - return true; + affectedObjects.add(card); } - return false; + return !affectedObjects.isEmpty(); } @Override diff --git a/Mage.Sets/src/mage/cards/a/AssaultSuit.java b/Mage.Sets/src/mage/cards/a/AssaultSuit.java index c289a7091e69..fa4827d1996f 100644 --- a/Mage.Sets/src/mage/cards/a/AssaultSuit.java +++ b/Mage.Sets/src/mage/cards/a/AssaultSuit.java @@ -1,7 +1,7 @@ package mage.cards.a; +import mage.MageItem; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.ContinuousEffectImpl; @@ -12,6 +12,7 @@ import mage.abilities.effects.common.continuous.GainControlTargetEffect; import mage.abilities.keyword.EquipAbility; import mage.abilities.keyword.HasteAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; @@ -20,7 +21,7 @@ import mage.players.Player; import mage.target.targetpointer.FixedTarget; -import java.util.Optional; +import java.util.List; import java.util.UUID; /** @@ -78,12 +79,24 @@ public AssaultSuitCantBeSacrificed copy() { } @Override - public boolean apply(Game game, Ability source) { - Optional.ofNullable(source.getSourcePermanentIfItStillExists(game)) - .map(Permanent::getAttachedTo) - .map(game::getPermanent) - .ifPresent(permanent -> permanent.setCanBeSacrificed(false)); - return true; + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + ((Permanent) object).setCanBeSacrificed(false); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + Permanent attachment = source.getSourcePermanentIfItStillExists(game); + if (attachment == null || attachment.getAttachedTo() == null) { + return false; + } + Permanent permanent = game.getPermanent(attachment.getAttachedTo()); + if (permanent != null) { + affectedObjects.add(permanent); + return true; + } + return false; } } diff --git a/Mage.Sets/src/mage/cards/a/AvenMimeomancer.java b/Mage.Sets/src/mage/cards/a/AvenMimeomancer.java index eae60c1968cb..8f6ecc0a7e49 100644 --- a/Mage.Sets/src/mage/cards/a/AvenMimeomancer.java +++ b/Mage.Sets/src/mage/cards/a/AvenMimeomancer.java @@ -1,13 +1,13 @@ package mage.cards.a; -import java.util.UUID; import mage.MageInt; +import mage.MageItem; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.common.counter.AddCountersTargetEffect; import mage.abilities.keyword.FlyingAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; @@ -16,6 +16,9 @@ import mage.game.permanent.Permanent; import mage.target.common.TargetCreaturePermanent; +import java.util.List; +import java.util.UUID; + /** * * @author jeffwadsworth @@ -37,7 +40,6 @@ public AvenMimeomancer(UUID ownerId, CardSetInfo setInfo) { Ability ability = new BeginningOfUpkeepTriggeredAbility(new AddCountersTargetEffect(CounterType.FEATHER.createInstance()), true); ability.addTarget(new TargetCreaturePermanent()); ability.addEffect(new AvenEffect()); - ability.addEffect(new AvenEffect2()); this.addAbility(ability); } @@ -54,7 +56,7 @@ public AvenMimeomancer copy() { class AvenEffect extends ContinuousEffectImpl { AvenEffect() { - super(Duration.Custom, Layer.PTChangingEffects_7, SubLayer.SetPT_7b, Outcome.BoostCreature); + super(Duration.Custom, Outcome.BoostCreature); this.staticText = "If you do, that creature has base power and toughness 3/1 and has flying for as long as it has a feather counter on it"; } @@ -68,59 +70,37 @@ public AvenEffect copy() { } @Override - public boolean apply(Game game, Ability source) { - Permanent target = game.getPermanent(getTargetPointer().getFirst(game, source)); - if (target == null) { - return false; + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; + switch (layer) { + case AbilityAddingRemovingEffects_6: + permanent.addAbility(FlyingAbility.getInstance(), source.getSourceId(), game); + break; + case PTChangingEffects_7: + if (sublayer == SubLayer.SetPT_7b) { + permanent.getPower().setModifiedBaseValue(3); + permanent.getToughness().setModifiedBaseValue(1); + } + break; + } } - target.getPower().setModifiedBaseValue(3); - target.getToughness().setModifiedBaseValue(1); - return true; } @Override - public boolean isInactive(Ability source, Game game) { - Permanent creature = game.getPermanent(getTargetPointer().getFirst(game, source)); - if (creature != null && creature.getCounters(game).getCount(CounterType.FEATHER) < 1) { - return true; - } - return false; - } -} - -class AvenEffect2 extends ContinuousEffectImpl { - - public AvenEffect2() { - super(Duration.Custom, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.BoostCreature); - } - - private AvenEffect2(final AvenEffect2 effect) { - super(effect); - } - - @Override - public AvenEffect2 copy() { - return new AvenEffect2(this); - } - - @Override - public boolean apply(Game game, Ability source) { + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Permanent target = game.getPermanent(getTargetPointer().getFirst(game, source)); - if (target != null) { - if (!target.getAbilities().contains(FlyingAbility.getInstance())) { - target.addAbility(FlyingAbility.getInstance(), source.getSourceId(), game); - return true; - } + if (target == null || target.getCounters(game).getCount(CounterType.FEATHER) < 1) { + this.discard(); + return false; } - return false; + affectedObjects.add(target); + return true; } @Override - public boolean isInactive(Ability source, Game game) { - Permanent creature = game.getPermanent(getTargetPointer().getFirst(game, source)); - if (creature != null && creature.getCounters(game).getCount(CounterType.FEATHER) < 1) { - return true; - } - return false; + public boolean hasLayer(Layer layer) { + return layer == Layer.AbilityAddingRemovingEffects_6 + || layer == Layer.PTChangingEffects_7; } } diff --git a/Mage.Sets/src/mage/cards/a/AwakenedAwareness.java b/Mage.Sets/src/mage/cards/a/AwakenedAwareness.java index 852ae736ffaf..36ce0f26a32e 100644 --- a/Mage.Sets/src/mage/cards/a/AwakenedAwareness.java +++ b/Mage.Sets/src/mage/cards/a/AwakenedAwareness.java @@ -1,23 +1,25 @@ package mage.cards.a; -import java.util.UUID; - +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.dynamicvalue.common.GetXValue; import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.common.AttachEffect; import mage.abilities.effects.common.counter.AddCountersAttachedEffect; +import mage.abilities.keyword.EnchantAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; import mage.constants.*; -import mage.abilities.effects.common.AttachEffect; import mage.counters.CounterType; import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.TargetPermanent; -import mage.abilities.keyword.EnchantAbility; -import mage.cards.CardImpl; -import mage.cards.CardSetInfo; + +import java.util.List; +import java.util.UUID; /** * @@ -72,7 +74,16 @@ public AwakenedAwarenessEffect copy() { } @Override - public boolean apply(Game game, Ability source) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; + permanent.getPower().setModifiedBaseValue(1); + permanent.getToughness().setModifiedBaseValue(1); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Permanent enchantment = source.getSourcePermanentIfItStillExists(game); if (enchantment == null) { return false; @@ -82,9 +93,7 @@ public boolean apply(Game game, Ability source) { if (creature == null || !creature.isCreature(game)) { return false; } - - creature.getPower().setModifiedBaseValue(1); - creature.getToughness().setModifiedBaseValue(1); + affectedObjects.add(creature); return true; } } diff --git a/Mage.Sets/src/mage/cards/a/AwakenerDruid.java b/Mage.Sets/src/mage/cards/a/AwakenerDruid.java index 3fbe8362f5fe..9aff1ace8d74 100644 --- a/Mage.Sets/src/mage/cards/a/AwakenerDruid.java +++ b/Mage.Sets/src/mage/cards/a/AwakenerDruid.java @@ -1,18 +1,22 @@ package mage.cards.a; import mage.MageInt; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.effects.common.continuous.BecomesCreatureTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Layer; +import mage.constants.SubType; import mage.filter.FilterPermanent; import mage.game.Game; -import mage.game.permanent.Permanent; import mage.game.permanent.token.TokenImpl; import mage.target.TargetPermanent; +import java.util.List; import java.util.UUID; /** @@ -64,13 +68,12 @@ public AwakenerDruidBecomesCreatureEffect copy() { } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - Permanent sourcePermanent = game.getPermanent(source.getSourceId()); - if (sourcePermanent == null) { + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + if (game.getPermanent(source.getSourceId()) == null) { this.discard(); return false; } - return super.apply(layer, sublayer, source, game); + return super.queryAffectedObjects(layer, source, game, affectedObjects); } } diff --git a/Mage.Sets/src/mage/cards/b/BackdraftHellkite.java b/Mage.Sets/src/mage/cards/b/BackdraftHellkite.java index 28694b3bc58d..be87f64396ba 100644 --- a/Mage.Sets/src/mage/cards/b/BackdraftHellkite.java +++ b/Mage.Sets/src/mage/cards/b/BackdraftHellkite.java @@ -1,6 +1,7 @@ package mage.cards.b; import mage.MageInt; +import mage.MageItem; import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; @@ -14,6 +15,7 @@ import mage.game.Game; import mage.players.Player; +import java.util.List; import java.util.Objects; import java.util.UUID; @@ -82,24 +84,24 @@ public void init(Ability source, Game game) { } @Override - public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - if (player == null) { - return false; + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Card card = (Card) object; + FlashbackAbility ability = new FlashbackAbility(card, card.getManaCost()); + ability.setSourceId(card.getId()); + ability.setControllerId(card.getOwnerId()); + game.getState().addOtherAbility(card, ability); } - player.getGraveyard() - .stream() - .filter(cardId -> affectedObjectList.contains(new MageObjectReference(cardId, game))) - .forEachOrdered(cardId -> { - Card card = game.getCard(cardId); - if (card == null) { - return; - } - FlashbackAbility ability = new FlashbackAbility(card, card.getManaCost()); - ability.setSourceId(cardId); - ability.setControllerId(card.getOwnerId()); - game.getState().addOtherAbility(card, ability); - }); - return true; + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + for (MageObjectReference mor : affectedObjectList) { + Card card = mor.getCard(game); + if (card != null) { + affectedObjects.add(card); + } + } + return !affectedObjects.isEmpty(); } } diff --git a/Mage.Sets/src/mage/cards/b/BannerOfKinship.java b/Mage.Sets/src/mage/cards/b/BannerOfKinship.java index 24bfa8eaaf2e..ec18d2bafa85 100644 --- a/Mage.Sets/src/mage/cards/b/BannerOfKinship.java +++ b/Mage.Sets/src/mage/cards/b/BannerOfKinship.java @@ -1,5 +1,6 @@ package mage.cards.b; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.SimpleStaticAbility; @@ -10,12 +11,12 @@ import mage.cards.CardSetInfo; import mage.constants.*; import mage.counters.CounterType; -import mage.filter.StaticFilters; import mage.filter.common.FilterControlledCreaturePermanent; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import java.util.List; import java.util.UUID; /** @@ -94,20 +95,29 @@ public BannerOfKinshipBoostEffect copy() { } @Override - public boolean apply(Game game, Ability source) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + int boost = game.getPermanent(source.getSourceId()) + .getCounters(game) + .getCount(CounterType.FELLOWSHIP); + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; + permanent.addPower(boost); + permanent.addToughness(boost); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent != null) { - SubType subtype = (SubType) game.getState().getValue(permanent.getId() + "_type"); - if (subtype != null) { - for (Permanent perm : game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURES, source.getControllerId(), game)) { - if (perm.hasSubtype(subtype, game)) { - int boost = permanent.getCounters(game).getCount(CounterType.FELLOWSHIP); - perm.addPower(boost); - perm.addToughness(boost); - } - } - } + if (permanent == null) { + return false; } - return true; + SubType subtype = (SubType) game.getState().getValue(source.getSourceId() + "_type"); + if (subtype == null) { + return false; + } + FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent(subtype); + affectedObjects.addAll(game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game)); + return !affectedObjects.isEmpty(); } } diff --git a/Mage.Sets/src/mage/cards/b/BeastmasterAscension.java b/Mage.Sets/src/mage/cards/b/BeastmasterAscension.java index f88ede4d8920..ebc119e6dfe5 100644 --- a/Mage.Sets/src/mage/cards/b/BeastmasterAscension.java +++ b/Mage.Sets/src/mage/cards/b/BeastmasterAscension.java @@ -2,7 +2,7 @@ package mage.cards.b; -import java.util.UUID; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.AttacksCreatureYouControlTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; @@ -12,11 +12,14 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; -import mage.constants.Zone; +import mage.constants.Layer; import mage.counters.CounterType; import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.List; +import java.util.UUID; + /** * * @author BetaSteward_at_googlemail.com @@ -54,12 +57,12 @@ private BeastmasterAscensionEffect(final BeastmasterAscensionEffect effect) { } @Override - public boolean apply(Game game, Ability source) { + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent != null && permanent.getCounters(game).getCount(CounterType.QUEST) > 6) { - super.apply(game, source); + if (permanent == null || permanent.getCounters(game).getCount(CounterType.QUEST) < 7) { + return false; } - return false; + return super.queryAffectedObjects(layer, source, game, affectedObjects); } @Override diff --git a/Mage.Sets/src/mage/cards/b/BelloBardOfTheBrambles.java b/Mage.Sets/src/mage/cards/b/BelloBardOfTheBrambles.java index c823c0bf1a70..e00b57bd7eed 100644 --- a/Mage.Sets/src/mage/cards/b/BelloBardOfTheBrambles.java +++ b/Mage.Sets/src/mage/cards/b/BelloBardOfTheBrambles.java @@ -1,6 +1,7 @@ package mage.cards.b; import mage.MageInt; +import mage.MageItem; import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; @@ -19,7 +20,8 @@ import mage.game.Game; import mage.game.permanent.Permanent; -import java.util.Iterator; +import java.util.ArrayList; +import java.util.List; import java.util.UUID; /** @@ -81,46 +83,59 @@ private BelloBardOfTheBramblesEffect(final BelloBardOfTheBramblesEffect effect) } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - if (!source.isControlledBy(game.getActivePlayerId())) { - return false; - } - switch (layer) { - case TypeChangingEffects_4: - affectedObjectList.clear(); - for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game)) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; + switch (layer) { + case TypeChangingEffects_4: permanent.addCardType(game, CardType.CREATURE); permanent.addSubType(game, SubType.ELEMENTAL); - affectedObjectList.add(new MageObjectReference(permanent, game)); - } - return true; - case AbilityAddingRemovingEffects_6: - for (Iterator it = affectedObjectList.iterator(); it.hasNext(); ) { - Permanent permanent = it.next().getPermanent(game); - if (permanent == null) { - continue; - } + break; + case AbilityAddingRemovingEffects_6: permanent.addAbility(IndestructibleAbility.getInstance(), source.getSourceId(), game); permanent.addAbility(HasteAbility.getInstance(), source.getSourceId(), game); permanent.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new DrawCardSourceControllerEffect(1)), source.getSourceId(), game); - } - return true; - case PTChangingEffects_7: - if (sublayer != SubLayer.SetPT_7b) { - return false; - } - for (Iterator it = affectedObjectList.iterator(); it.hasNext(); ) { - Permanent permanent = it.next().getPermanent(game); - if (permanent == null) { - continue; + break; + case PTChangingEffects_7: + if (sublayer == SubLayer.SetPT_7b) { + permanent.getPower().setModifiedBaseValue(4); + permanent.getToughness().setModifiedBaseValue(4); } - permanent.getPower().setModifiedBaseValue(4); - permanent.getToughness().setModifiedBaseValue(4); + break; + } + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + if (!source.isControlledBy(game.getActivePlayerId())) { + return false; + } + if (layer == Layer.TypeChangingEffects_4) { + affectedObjectList.clear(); + for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game)) { + affectedObjectList.add(new MageObjectReference(permanent, game)); + affectedObjects.add(permanent); + } + } else { + for (MageObjectReference mor : affectedObjectList) { + Permanent permanent = mor.getPermanent(game); + if (permanent != null) { + affectedObjects.add(permanent); } - return true; - default: - return false; + } + } + return !affectedObjects.isEmpty(); + } + + @Override + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + List affectedObjects = new ArrayList<>(); + if (queryAffectedObjects(layer, source, game, affectedObjects)) { + applyToObjects(layer, sublayer, source, game, affectedObjects); + return true; } + return false; } @Override @@ -130,11 +145,6 @@ public boolean hasLayer(Layer layer) { || layer == Layer.PTChangingEffects_7; } - @Override - public boolean apply(Game game, Ability source) { - return false; - } - @Override public BelloBardOfTheBramblesEffect copy() { return new BelloBardOfTheBramblesEffect(this); diff --git a/Mage.Sets/src/mage/cards/b/Biotransference.java b/Mage.Sets/src/mage/cards/b/Biotransference.java index 5f13df83656d..10912bbe8154 100644 --- a/Mage.Sets/src/mage/cards/b/Biotransference.java +++ b/Mage.Sets/src/mage/cards/b/Biotransference.java @@ -1,5 +1,7 @@ package mage.cards.b; +import mage.MageItem; +import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SpellCastControllerTriggeredAbility; @@ -67,7 +69,14 @@ public BiotransferenceEffect copy() { } @Override - public boolean apply(Game game, Ability source) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + ((MageObject) object).addCardType(game, CardType.ARTIFACT); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Player controller = game.getPlayer(source.getControllerId()); if (controller == null) { return false; @@ -77,26 +86,26 @@ public boolean apply(Game game, Ability source) { for (UUID cardId : controller.getGraveyard()) { Card card = game.getCard(cardId); if (card != null && card.isCreature(game) && !card.isArtifact(game)) { - card.addCardType(game, CardType.ARTIFACT); + affectedObjects.add(card); } } // on Hand for (UUID cardId : controller.getHand()) { Card card = game.getCard(cardId); if (card != null && card.isCreature(game) && !card.isArtifact(game)) { - card.addCardType(game, CardType.ARTIFACT); + affectedObjects.add(card); } } // in Exile for (Card card : game.getState().getExile().getAllCards(game, source.getControllerId())) { if (card.isCreature(game) && !card.isArtifact(game)) { - card.addCardType(game, CardType.ARTIFACT); + affectedObjects.add(card); } } // in Library (e.g. for Mystical Teachings) for (Card card : controller.getLibrary().getCards(game)) { if (card.isOwnedBy(controller.getId()) && card.isCreature(game) && !card.isArtifact(game)) { - card.addCardType(game, CardType.ARTIFACT); + affectedObjects.add(card); } } // commander in command zone @@ -105,7 +114,7 @@ public boolean apply(Game game, Ability source) { Card card = game.getCard((commandObject).getId()); if (card != null && card.isOwnedBy(controller.getId()) && card.isCreature(game) && !card.isArtifact(game)) { - card.addCardType(game, CardType.ARTIFACT); + affectedObjects.add(card); } } } @@ -117,7 +126,7 @@ public boolean apply(Game game, Ability source) { && stackObject.isCreature(game) && !stackObject.isArtifact(game)) { Card card = ((Spell) stackObject).getCard(); - card.addCardType(game, CardType.ARTIFACT); + affectedObjects.add(card); } } // creatures you control @@ -125,10 +134,9 @@ public boolean apply(Game game, Ability source) { new FilterControlledCreaturePermanent(), source.getControllerId(), game); for (Permanent creature : creatures) { if (creature != null) { - creature.addCardType(game, CardType.ARTIFACT); + affectedObjects.add(creature); } } - return true; - + return !affectedObjects.isEmpty(); } } diff --git a/Mage.Sets/src/mage/cards/b/BladeOfTheOni.java b/Mage.Sets/src/mage/cards/b/BladeOfTheOni.java index 50565152d7d8..fee72e142f99 100644 --- a/Mage.Sets/src/mage/cards/b/BladeOfTheOni.java +++ b/Mage.Sets/src/mage/cards/b/BladeOfTheOni.java @@ -1,6 +1,7 @@ package mage.cards.b; import mage.MageInt; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousEffectImpl; @@ -12,6 +13,8 @@ import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.ArrayList; +import java.util.List; import java.util.UUID; /** @@ -65,7 +68,31 @@ public BladeOfTheOniEffect copy() { } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; + switch (layer) { + case TypeChangingEffects_4: + permanent.addSubType(game, SubType.DEMON); + break; + case ColorChangingEffects_5: + permanent.getColor(game).setBlack(true); + break; + case AbilityAddingRemovingEffects_6: + permanent.addAbility(new MenaceAbility(false), source.getSourceId(), game); + break; + case PTChangingEffects_7: + if (sublayer == SubLayer.SetPT_7b) { + permanent.getPower().setModifiedBaseValue(5); + permanent.getToughness().setModifiedBaseValue(5); + } + break; + } + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Permanent sourcePermanent = source.getSourcePermanentIfItStillExists(game); if (sourcePermanent == null) { return false; @@ -74,29 +101,17 @@ public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) if (permanent == null) { return false; } - switch (layer) { - case AbilityAddingRemovingEffects_6: - permanent.addAbility(new MenaceAbility(false), source.getSourceId(), game); - return true; - case ColorChangingEffects_5: - permanent.getColor(game).setBlack(true); - return true; - case TypeChangingEffects_4: - permanent.addSubType(game, SubType.DEMON); - return true; - case PTChangingEffects_7: - if (sublayer != SubLayer.SetPT_7b) { - return false; - } - permanent.getPower().setModifiedBaseValue(5); - permanent.getToughness().setModifiedBaseValue(5); - return true; - } - return false; + affectedObjects.add(permanent); + return true; } @Override - public boolean apply(Game game, Ability source) { + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + List affectedObjects = new ArrayList<>(); + if (queryAffectedObjects(layer, source, game, affectedObjects)) { + applyToObjects(layer, sublayer, source, game, affectedObjects); + return true; + } return false; } diff --git a/Mage.Sets/src/mage/cards/b/BloodBaronOfVizkopa.java b/Mage.Sets/src/mage/cards/b/BloodBaronOfVizkopa.java index fc245f5645f7..088ecc6d1069 100644 --- a/Mage.Sets/src/mage/cards/b/BloodBaronOfVizkopa.java +++ b/Mage.Sets/src/mage/cards/b/BloodBaronOfVizkopa.java @@ -1,7 +1,7 @@ package mage.cards.b; -import java.util.UUID; import mage.MageInt; +import mage.MageItem; import mage.ObjectColor; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; @@ -16,6 +16,10 @@ import mage.game.permanent.Permanent; import mage.players.Player; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + public final class BloodBaronOfVizkopa extends CardImpl { public BloodBaronOfVizkopa(UUID ownerId, CardSetInfo setInfo) { @@ -61,7 +65,25 @@ public BloodBaronOfVizkopaEffect copy() { } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent creature = (Permanent) object; + switch (layer) { + case PTChangingEffects_7: + if (sublayer == SubLayer.ModifyPT_7c) { + creature.addPower(6); + creature.addToughness(6); + } + break; + case AbilityAddingRemovingEffects_6: + creature.addAbility(FlyingAbility.getInstance(), source.getSourceId(), game); + break; + } + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { if (!conditionState(source, game)) { return false; } @@ -70,24 +92,18 @@ public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) if (creature == null) { return false; } + affectedObjects.add(creature); + return true; + } - switch (layer) { - case PTChangingEffects_7: - if (sublayer == SubLayer.ModifyPT_7c) { - creature.addPower(6); - creature.addToughness(6); - } - break; - case AbilityAddingRemovingEffects_6: - if (sublayer == SubLayer.NA) { - creature.addAbility(FlyingAbility.getInstance(), source.getSourceId(), game); - } - break; - default: - return false; + @Override + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + List affectedObjects = new ArrayList<>(); + if (queryAffectedObjects(layer, source, game, affectedObjects)) { + applyToObjects(layer, sublayer, source, game, affectedObjects); + return true; } - - return true; + return false; } private boolean conditionState(Ability source, Game game) { @@ -104,11 +120,6 @@ private boolean conditionState(Ability source, Game game) { 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); diff --git a/Mage.Sets/src/mage/cards/b/BloodMoon.java b/Mage.Sets/src/mage/cards/b/BloodMoon.java index 40b3f9a2b238..3f1a2707b3f0 100644 --- a/Mage.Sets/src/mage/cards/b/BloodMoon.java +++ b/Mage.Sets/src/mage/cards/b/BloodMoon.java @@ -1,5 +1,6 @@ package mage.cards.b; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousEffectImpl; @@ -12,6 +13,7 @@ import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.List; import java.util.UUID; /** @@ -44,7 +46,7 @@ static class BloodMoonEffect extends ContinuousEffectImpl { } BloodMoonEffect() { - super(Duration.WhileOnBattlefield, Outcome.Detriment); + super(Duration.WhileOnBattlefield, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Detriment); this.staticText = "Nonbasic lands are Mountains"; this.dependencyTypes.add(DependencyType.BecomeMountain); this.dependendToTypes.add(DependencyType.BecomeNonbasicLand); @@ -54,37 +56,29 @@ private 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.removeAllSubTypes(game, SubTypeSet.NonBasicLandType); - land.addSubType(game, SubType.MOUNTAIN); - land.removeAllAbilities(source.getSourceId(), game); - land.addAbility(new RedManaAbility(), source.getSourceId(), game); - break; - } + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent land = (Permanent) object; + // 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.removeAllSubTypes(game, SubTypeSet.NonBasicLandType); + land.addSubType(game, SubType.MOUNTAIN); + land.removeAllAbilities(source.getSourceId(), game); + land.addAbility(new RedManaAbility(), source.getSourceId(), game); } - return true; } @Override - public boolean hasLayer(Layer layer) { - return layer == Layer.TypeChangingEffects_4; + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + affectedObjects.addAll(game.getBattlefield().getActivePermanents(filter, source.getControllerId(), game)); + return !affectedObjects.isEmpty(); } } } diff --git a/Mage.Sets/src/mage/cards/b/BloodSun.java b/Mage.Sets/src/mage/cards/b/BloodSun.java index 57c3b169d85e..0c5774f23cfd 100644 --- a/Mage.Sets/src/mage/cards/b/BloodSun.java +++ b/Mage.Sets/src/mage/cards/b/BloodSun.java @@ -1,6 +1,7 @@ package mage.cards.b; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; @@ -46,7 +47,7 @@ public BloodSun copy() { class BloodSunEffect extends ContinuousEffectImpl { BloodSunEffect(Duration duration) { - super(duration, Outcome.LoseAbility); + super(duration, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.LoseAbility); staticText = "all lands lose all abilities except mana abilities"; } @@ -60,35 +61,26 @@ public BloodSunEffect copy() { } @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(StaticFilters.FILTER_LANDS, player.getId(), source, game)) { - switch (layer) { - case AbilityAddingRemovingEffects_6: - List toRemove = new ArrayList<>(); - permanent.getAbilities().forEach(ability -> { - if (!ability.getAbilityType().isManaAbility()) { - toRemove.add(ability); - } - }); - permanent.removeAbilities(toRemove, source.getSourceId(), game); - break; + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; + List toRemove = new ArrayList<>(); + permanent.getAbilities().forEach(ability -> { + if (!ability.getAbilityType().isManaAbility()) { + toRemove.add(ability); } - } - return true; + }); + permanent.removeAbilities(toRemove, source.getSourceId(), game); } - return false; - } - - @Override - public boolean apply(Game game, Ability source) { - return false; } @Override - public boolean hasLayer(Layer layer) { - return layer == Layer.AbilityAddingRemovingEffects_6; + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + Player player = game.getPlayer(source.getControllerId()); + if (player == null) { + return false; + } + affectedObjects.addAll(game.getBattlefield().getActivePermanents(StaticFilters.FILTER_LANDS, player.getId(), source, game)); + return !affectedObjects.isEmpty(); } - } diff --git a/Mage.Sets/src/mage/cards/b/BloodlordOfVaasgoth.java b/Mage.Sets/src/mage/cards/b/BloodlordOfVaasgoth.java index b545e6e26582..337007461dfa 100644 --- a/Mage.Sets/src/mage/cards/b/BloodlordOfVaasgoth.java +++ b/Mage.Sets/src/mage/cards/b/BloodlordOfVaasgoth.java @@ -2,6 +2,8 @@ package mage.cards.b; import mage.MageInt; +import mage.MageItem; +import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.common.SpellCastControllerTriggeredAbility; import mage.abilities.effects.ContinuousEffectImpl; @@ -15,6 +17,7 @@ import mage.game.permanent.Permanent; import mage.game.stack.Spell; +import java.util.List; import java.util.UUID; /** @@ -59,8 +62,6 @@ public BloodlordOfVaasgoth copy() { class BloodlordOfVaasgothEffect extends ContinuousEffectImpl { private Ability ability = new BloodthirstAbility(3); - private int zoneChangeCounter; - private UUID permanentId; BloodlordOfVaasgothEffect() { super(Duration.OneUse, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility); @@ -70,8 +71,6 @@ class BloodlordOfVaasgothEffect extends ContinuousEffectImpl { private BloodlordOfVaasgothEffect(final BloodlordOfVaasgothEffect effect) { super(effect); this.ability = effect.ability.copy(); - this.zoneChangeCounter = effect.zoneChangeCounter; - this.permanentId = effect.permanentId; } @Override @@ -84,25 +83,39 @@ public void init(Ability source, Game game) { super.init(source, game); Spell object = game.getStack().getSpell(getTargetPointer().getFirst(game, source)); if (object != null) { - zoneChangeCounter = game.getState().getZoneChangeCounter(object.getSourceId()) + 1; - permanentId = object.getSourceId(); + int zcc = game.getState().getZoneChangeCounter(object.getSourceId()) + 1; + affectedObjectList.add(new MageObjectReference(object.getSourceId(), zcc, game)); } } @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(permanentId); - if (permanent != null && permanent.getZoneChangeCounter(game) <= zoneChangeCounter) { - permanent.addAbility(ability, source.getSourceId(), game); - } else { - if (game.getState().getZoneChangeCounter(permanentId) >= zoneChangeCounter) { - discard(); + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + if (object instanceof Spell) { + game.getState().addOtherAbility(((Spell) object).getCard(), ability, true); + } else { + ((Permanent) object).addAbility(ability, source.getSourceId(), game); } - Spell spell = game.getStack().getSpell(getTargetPointer().getFirst(game, source)); - if (spell != null) { // Bloodthirst checked while spell is on the stack so needed to give it already to the spell - game.getState().addOtherAbility(spell.getCard(), ability, true); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + Spell spell = game.getStack().getSpell(getTargetPointer().getFirst(game, source)); + if (spell != null) { // Bloodthirst checked while spell is on the stack so needed to give it already to the spell + affectedObjects.add(spell); + } else { + for (MageObjectReference mor : affectedObjectList) { + Permanent permanent = mor.getPermanent(game); + if (permanent != null) { + affectedObjects.add(permanent); + } } } + if (affectedObjects.isEmpty()) { + this.discard(); + return false; + } return true; } diff --git a/Mage.Sets/src/mage/cards/b/BludgeonBrawl.java b/Mage.Sets/src/mage/cards/b/BludgeonBrawl.java index 8788d6e44366..2cf8c52eed97 100644 --- a/Mage.Sets/src/mage/cards/b/BludgeonBrawl.java +++ b/Mage.Sets/src/mage/cards/b/BludgeonBrawl.java @@ -1,6 +1,7 @@ package mage.cards.b; +import mage.MageItem; import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; @@ -16,6 +17,8 @@ import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.ArrayList; +import java.util.List; import java.util.UUID; /** @@ -59,15 +62,9 @@ private BludgeonBrawlEffect(final BludgeonBrawlEffect effect) { } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - if (layer == Layer.TypeChangingEffects_4) { - affectedObjectList.clear(); - for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game)) { - affectedObjectList.add(new MageObjectReference(permanent, game)); - } - } - for (MageObjectReference mor : affectedObjectList) { - Permanent permanent = mor.getPermanent(game); + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; switch (layer) { case TypeChangingEffects_4: permanent.addSubType(game, SubType.EQUIPMENT); @@ -80,11 +77,33 @@ public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) permanent.addAbility(new EquipAbility(mv, false), source.getSourceId(), game); } } - return true; } @Override - public boolean apply(Game game, Ability source) { + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + if (layer == Layer.TypeChangingEffects_4) { + affectedObjectList.clear(); + for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game)) { + affectedObjectList.add(new MageObjectReference(permanent, game)); + affectedObjects.add(permanent); + } + } else { + for (MageObjectReference mor : affectedObjectList) { + Permanent permanent = mor.getPermanent(game); + if (permanent != null) { + affectedObjects.add(permanent); + } + } + } + return !affectedObjects.isEmpty(); + } + @Override + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + List affectedObjects = new ArrayList<>(); + if (queryAffectedObjects(layer, source, game, affectedObjects)) { + applyToObjects(layer, sublayer, source, game, affectedObjects); + return true; + } return false; } diff --git a/Mage.Sets/src/mage/cards/b/BlueDragon.java b/Mage.Sets/src/mage/cards/b/BlueDragon.java index 3ba5018301b2..80c5a1841205 100644 --- a/Mage.Sets/src/mage/cards/b/BlueDragon.java +++ b/Mage.Sets/src/mage/cards/b/BlueDragon.java @@ -1,6 +1,7 @@ package mage.cards.b; import mage.MageInt; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.effects.ContinuousEffectImpl; @@ -16,6 +17,9 @@ import mage.target.TargetPermanent; import mage.target.common.TargetOpponentsCreaturePermanent; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import java.util.UUID; /** @@ -61,6 +65,8 @@ public BlueDragon copy() { class BlueDragonEffect extends ContinuousEffectImpl { + Map powerMap = new HashMap<>(); + BlueDragonEffect() { super(Duration.UntilYourNextTurn, Layer.PTChangingEffects_7, SubLayer.ModifyPT_7c, Outcome.UnboostCreature); this.staticText = "until your next turn, target creature an opponent controls gets -3/-0, up to one other target creature gets -2/-0, and up to one other target creature gets -1/-0"; @@ -68,6 +74,7 @@ class BlueDragonEffect extends ContinuousEffectImpl { private BlueDragonEffect(final BlueDragonEffect effect) { super(effect); + powerMap.putAll(effect.powerMap); } @Override @@ -76,17 +83,24 @@ public BlueDragonEffect copy() { } @Override - public boolean apply(Game game, Ability source) { - int power = -3; - int affectedTargets = 0; + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; + int power = -4 + powerMap.get(permanent.getId()); + permanent.addPower(power); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + powerMap.clear(); for (Target target : source.getTargets()) { Permanent permanent = game.getPermanent(target.getFirstTarget()); - if (permanent != null && permanent.isCreature(game)) { - permanent.addPower(power); - affectedTargets++; + if (permanent != null && permanent.isCreature()) { + affectedObjects.add(permanent); + powerMap.put(permanent.getId(), target.getTargetTag()); } - power++; } - return affectedTargets > 0; + return !affectedObjects.isEmpty(); } } diff --git a/Mage.Sets/src/mage/cards/b/Bravado.java b/Mage.Sets/src/mage/cards/b/Bravado.java index 5d8114d786d7..0f84598e0505 100644 --- a/Mage.Sets/src/mage/cards/b/Bravado.java +++ b/Mage.Sets/src/mage/cards/b/Bravado.java @@ -1,6 +1,7 @@ package mage.cards.b; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousEffectImpl; @@ -15,6 +16,7 @@ import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import java.util.List; import java.util.UUID; /** @@ -66,20 +68,27 @@ public BravadoBoostEnchantedEffect copy() { } @Override - public boolean apply(Game game, Ability source) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent(); int count = game.getBattlefield().count(filter, source.getControllerId(), source, game) - 1; - if (count > 0) { - Permanent enchantment = game.getPermanent(source.getSourceId()); - if (enchantment != null && enchantment.getAttachedTo() != null) { - Permanent creature = game.getPermanent(enchantment.getAttachedTo()); - if (creature != null) { - creature.addPower(count); - creature.addToughness(count); - return true; - } - } + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; + permanent.addPower(count); + permanent.addToughness(count); } - return false; + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + Permanent enchantment = game.getPermanent(source.getSourceId()); + if (enchantment == null || enchantment.getAttachedTo() == null) { + return false; + } + Permanent permanent = game.getPermanent(enchantment.getAttachedTo()); + if (permanent == null) { + return false; + } + affectedObjects.add(permanent); + return true; } } diff --git a/Mage.Sets/src/mage/cards/b/BronzehideLion.java b/Mage.Sets/src/mage/cards/b/BronzehideLion.java index 664726018505..d68cedd3bfc7 100644 --- a/Mage.Sets/src/mage/cards/b/BronzehideLion.java +++ b/Mage.Sets/src/mage/cards/b/BronzehideLion.java @@ -1,9 +1,7 @@ package mage.cards.b; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; import mage.MageInt; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.DiesSourceTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; @@ -26,6 +24,10 @@ import mage.target.common.TargetControlledCreaturePermanent; import mage.util.CardUtil; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + /** * @author LevelX2, TheElk801 */ @@ -124,12 +126,42 @@ private BronzehideLionContinuousEffect(final BronzehideLionContinuousEffect abil } @Override - public boolean apply(Game game, Ability source) { - return false; + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent lion = (Permanent) object; + switch (layer) { + case TypeChangingEffects_4: + lion.removeAllCardTypes(game); + lion.addCardType(game, CardType.ENCHANTMENT); + lion.removeAllSubTypes(game); + lion.addSubType(game, SubType.AURA); + break; + case AbilityAddingRemovingEffects_6: + List toRemove = new ArrayList<>(); + for (Ability ability : lion.getAbilities(game)) { + if (!lion.getSpellAbility().equals(ability)) { + toRemove.add(ability); + } + } + lion.removeAbilities(toRemove, source.getSourceId(), game); + + lion.getSpellAbility().getTargets().clear(); + lion.getSpellAbility().getEffects().clear(); + TargetPermanent auraTarget = new TargetControlledCreaturePermanent(); + lion.getSpellAbility().addTarget(auraTarget); + lion.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); + lion.addAbility(new EnchantAbility(auraTarget), source.getSourceId(), game); + + // add the activated ability + activatedAbility.setControllerId(source.getControllerId()); + lion.addAbility(activatedAbility, source.getSourceId(), game); + break; + } + } } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { if (game.getState().getZoneChangeCounter(source.getSourceId()) > zoneChangeCounter) { discard(); } @@ -140,38 +172,20 @@ public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) if (sourceObject == null) { return false; } - Permanent lion = sourceObject; - switch (layer) { - case TypeChangingEffects_4: - lion.removeAllCardTypes(game); - lion.addCardType(game, CardType.ENCHANTMENT); - lion.removeAllSubTypes(game); - lion.addSubType(game, SubType.AURA); - break; - case AbilityAddingRemovingEffects_6: - List toRemove = new ArrayList<>(); - for (Ability ability : lion.getAbilities(game)) { - if (!lion.getSpellAbility().equals(ability)) { - toRemove.add(ability); - } - } - lion.removeAbilities(toRemove, source.getSourceId(), game); - - lion.getSpellAbility().getTargets().clear(); - lion.getSpellAbility().getEffects().clear(); - TargetPermanent auraTarget = new TargetControlledCreaturePermanent(); - lion.getSpellAbility().addTarget(auraTarget); - lion.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); - lion.addAbility(new EnchantAbility(auraTarget), source.getSourceId(), game); - - // add the activated ability - activatedAbility.setControllerId(source.getControllerId()); - lion.addAbility(activatedAbility, source.getSourceId(), game); - break; - } + affectedObjects.add(sourceObject); return true; } + @Override + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + List affectedObjects = new ArrayList<>(); + if (queryAffectedObjects(layer, source, game, affectedObjects)) { + applyToObjects(layer, sublayer, source, game, affectedObjects); + return true; + } + return false; + } + @Override public boolean hasLayer(Layer layer) { return layer == Layer.TypeChangingEffects_4 || layer == Layer.AbilityAddingRemovingEffects_6; diff --git a/Mage.Sets/src/mage/cards/b/BrothersYamazaki.java b/Mage.Sets/src/mage/cards/b/BrothersYamazaki.java index 8de7ab25372b..9c2bb60d3f79 100644 --- a/Mage.Sets/src/mage/cards/b/BrothersYamazaki.java +++ b/Mage.Sets/src/mage/cards/b/BrothersYamazaki.java @@ -1,6 +1,7 @@ package mage.cards.b; import mage.MageInt; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousEffectImpl; @@ -89,16 +90,16 @@ public BrothersYamazakiIgnoreLegendRuleEffectEffect copy() { } @Override - public boolean apply(Game game, Ability source) { - List permanents = game.getBattlefield().getActivePermanents( - filter, source.getControllerId(), source, game - ); - if (permanents.size() != 2) { - return false; - } - for (Permanent permanent : permanents) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; permanent.setLegendRuleApplies(false); } - return true; + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + affectedObjects.addAll(game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game)); + return affectedObjects.size() == 2; } } diff --git a/Mage.Sets/src/mage/cards/b/BruenorBattlehammer.java b/Mage.Sets/src/mage/cards/b/BruenorBattlehammer.java index e3f1d885b5ca..1509d78e17a7 100644 --- a/Mage.Sets/src/mage/cards/b/BruenorBattlehammer.java +++ b/Mage.Sets/src/mage/cards/b/BruenorBattlehammer.java @@ -1,6 +1,7 @@ package mage.cards.b; import mage.MageInt; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousEffectImpl; @@ -18,6 +19,7 @@ import mage.watchers.Watcher; import java.util.HashSet; +import java.util.List; import java.util.Set; import java.util.UUID; @@ -69,11 +71,9 @@ public BruenorBattlehammerBoostEffect copy() { } @Override - public boolean apply(Game game, Ability source) { - for (Permanent permanent : game.getBattlefield().getActivePermanents( - StaticFilters.FILTER_CONTROLLED_CREATURE, - source.getControllerId(), source, game - )) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; int equipped = permanent .getAttachments() .stream() @@ -82,7 +82,15 @@ public boolean apply(Game game, Ability source) { .sum(); permanent.addPower(2 * equipped); } - return true; + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + affectedObjects.addAll(game.getBattlefield().getActivePermanents( + StaticFilters.FILTER_CONTROLLED_CREATURE, + source.getControllerId(), source, game + )); + return !affectedObjects.isEmpty(); } } diff --git a/Mage.Sets/src/mage/cards/b/BurdenOfProof.java b/Mage.Sets/src/mage/cards/b/BurdenOfProof.java index ccce64861775..d54d06436f79 100644 --- a/Mage.Sets/src/mage/cards/b/BurdenOfProof.java +++ b/Mage.Sets/src/mage/cards/b/BurdenOfProof.java @@ -1,5 +1,6 @@ package mage.cards.b; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.Condition; @@ -21,8 +22,8 @@ import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; -import java.util.Objects; -import java.util.Optional; +import java.util.ArrayList; +import java.util.List; import java.util.UUID; /** @@ -85,35 +86,45 @@ public BurdenOfProofEffect copy() { } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - if (layer != Layer.PTChangingEffects_7) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; + if (permanent.isControlledBy(source.getControllerId()) && permanent.hasSubtype(SubType.DETECTIVE, game)) { + if (sublayer == SubLayer.ModifyPT_7c) { + permanent.getPower().increaseBoostedValue(2); + permanent.getToughness().increaseBoostedValue(2); + } + } else if (sublayer == SubLayer.SetPT_7b) { + permanent.getPower().setModifiedBaseValue(1); + permanent.getToughness().setModifiedBaseValue(1); + } + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + Permanent enchantment = game.getPermanent(source.getSourceId()); + if (enchantment == null || enchantment.getAttachedTo() == null) { return false; } - Permanent permanent = Optional - .ofNullable(source.getSourcePermanentIfItStillExists(game)) - .filter(Objects::nonNull) - .map(Permanent::getAttachedTo) - .map(game::getPermanent) - .orElse(null); + Permanent permanent = game.getPermanent(enchantment.getAttachedTo()); if (permanent == null) { return false; } - if (permanent.isControlledBy(source.getControllerId()) && permanent.hasSubtype(SubType.DETECTIVE, game)) { - if (sublayer == SubLayer.ModifyPT_7c) { - permanent.getPower().increaseBoostedValue(2); - permanent.getToughness().increaseBoostedValue(2); - return true; - } - } else if (sublayer == SubLayer.SetPT_7b) { - permanent.getPower().setModifiedBaseValue(1); - permanent.getToughness().setModifiedBaseValue(1); - return true; - } - return false; + affectedObjects.add(permanent); + return true; } @Override - public boolean apply(Game game, Ability source) { + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + if (layer != Layer.PTChangingEffects_7) { + return false; + } + List affectedObjects = new ArrayList<>(); + if (queryAffectedObjects(layer, source, game, affectedObjects)) { + applyToObjects(layer, sublayer, source, game, affectedObjects); + return true; + } return false; } diff --git a/Mage.Sets/src/mage/cards/b/BurningCinderFuryOfCrimsonChaosFire.java b/Mage.Sets/src/mage/cards/b/BurningCinderFuryOfCrimsonChaosFire.java index 2067a9f6c337..f334d8b7aa60 100644 --- a/Mage.Sets/src/mage/cards/b/BurningCinderFuryOfCrimsonChaosFire.java +++ b/Mage.Sets/src/mage/cards/b/BurningCinderFuryOfCrimsonChaosFire.java @@ -1,5 +1,6 @@ package mage.cards.b; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; @@ -160,13 +161,19 @@ public BurningCinderFuryOfCrimsonChaosFireCreatureGainControlEffect copy() { } @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(source.getFirstTarget()); - permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); - if (permanent != null && controller != null) { - return permanent.changeControllerId(controller, game, source); + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + ((Permanent) object).changeControllerId(controller, game, source); } - return false; + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); + if (permanent != null) { + affectedObjects.add(permanent); + } + return !affectedObjects.isEmpty(); } } diff --git a/Mage.Sets/src/mage/cards/c/CagedSun.java b/Mage.Sets/src/mage/cards/c/CagedSun.java index bd34452308ff..17c915db9750 100644 --- a/Mage.Sets/src/mage/cards/c/CagedSun.java +++ b/Mage.Sets/src/mage/cards/c/CagedSun.java @@ -1,8 +1,6 @@ package mage.cards.c; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; +import mage.MageItem; import mage.Mana; import mage.ObjectColor; import mage.abilities.Ability; @@ -20,6 +18,10 @@ import mage.game.events.GameEvent; import mage.game.permanent.Permanent; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + /** * @author BetaSteward */ @@ -67,22 +69,30 @@ public CagedSunEffect2 copy() { } @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent != null) { - ObjectColor color = (ObjectColor) game.getState().getValue(permanent.getId() + "_color"); - if (color != null) { - for (Permanent perm : game.getBattlefield().getAllActivePermanents(filter, source.getControllerId(), game)) { - if (perm.getColor(game).contains(color)) { - perm.addPower(1); - perm.addToughness(1); - } - } + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + ObjectColor color = (ObjectColor) game.getState().getValue(source.getSourceId() + "_color"); + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; + if (permanent.getColor(game).contains(color)) { + permanent.addPower(1); + permanent.addToughness(1); } } - return true; } + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + Permanent permanent = game.getPermanent(source.getSourceId()); + if (permanent == null) { + return false; + } + ObjectColor color = (ObjectColor) game.getState().getValue(permanent.getId() + "_color"); + if (color == null) { + return false; + } + affectedObjects.addAll(game.getBattlefield().getAllActivePermanents(filter, source.getControllerId(), game)); + return !affectedObjects.isEmpty(); + } } class CagedSunTriggeredAbility extends TriggeredManaAbility { diff --git a/Mage.Sets/src/mage/cards/c/CairnWanderer.java b/Mage.Sets/src/mage/cards/c/CairnWanderer.java index 4c6029497c5f..67297d6886d3 100644 --- a/Mage.Sets/src/mage/cards/c/CairnWanderer.java +++ b/Mage.Sets/src/mage/cards/c/CairnWanderer.java @@ -1,10 +1,11 @@ package mage.cards.c; -import java.util.UUID; import mage.MageInt; +import mage.MageItem; +import mage.abilities.Abilities; +import mage.abilities.AbilitiesImpl; import mage.abilities.Ability; -import mage.abilities.MageSingleton; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.keyword.*; @@ -12,10 +13,13 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; +import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import java.util.*; + /** * * @author psykad @@ -47,6 +51,22 @@ public CairnWanderer copy() { static class CairnWandererEffect extends ContinuousEffectImpl { + private static final Set> KEYWORD_ABILITIES = new HashSet<>(Arrays.asList( + FlyingAbility.class, + FearAbility.class, + FirstStrikeAbility.class, + DoubleStrikeAbility.class, + DeathtouchAbility.class, + HasteAbility.class, + LandwalkAbility.class, + LifelinkAbility.class, + ProtectionAbility.class, + ReachAbility.class, + TrampleAbility.class, + ShroudAbility.class, + VigilanceAbility.class + )); + public CairnWandererEffect() { super(Duration.WhileOnBattlefield, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility); this.addDependedToType(DependencyType.AddingAbility); @@ -58,45 +78,48 @@ private CairnWandererEffect(final CairnWandererEffect effect) { } @Override - public boolean apply(Game game, Ability source) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + Abilities graveyardAbilities = new AbilitiesImpl<>(); + getAbilitiesInGraveyards(game, source, graveyardAbilities); + + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; + for (Ability ability : graveyardAbilities) { + if (isValidKeywordAbility(ability.getClass())) { + permanent.addAbility(ability, source.getSourceId(), game); + } + } + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Permanent sourcePermanent = game.getPermanent(source.getSourceId()); if (sourcePermanent == null) { return false; } + affectedObjects.add(sourcePermanent); + return true; + } + private void getAbilitiesInGraveyards(Game game, Ability source, Abilities graveyardAbilities) { for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) { Player player = game.getPlayer(playerId); - - if (player != null) { - for (Card card : player.getGraveyard().getCards(game)) { - if (card.isCreature(game)) { - for (Ability ability : card.getAbilities(game)) { - if (ability instanceof MageSingleton) { - if (ability instanceof FlyingAbility - || ability instanceof FearAbility - || ability instanceof FirstStrikeAbility - || ability instanceof DoubleStrikeAbility - || ability instanceof DeathtouchAbility - || ability instanceof HasteAbility - || ability instanceof LifelinkAbility - || ability instanceof ReachAbility - || ability instanceof TrampleAbility - || ability instanceof ShroudAbility - || ability instanceof VigilanceAbility) { - sourcePermanent.addAbility(ability, source.getSourceId(), game); - } - } else if (ability instanceof ProtectionAbility - || ability instanceof LandwalkAbility) { - sourcePermanent.addAbility(ability, source.getSourceId(), game); - } - } - } - } + if (player == null) { + continue; + } + for (Card card : player.getGraveyard().getCards(StaticFilters.FILTER_CARD_CREATURE, game)) { + graveyardAbilities.addAll(card.getAbilities(game)); } } + } - return true; + private boolean isValidKeywordAbility(Class abilityClass) { + return KEYWORD_ABILITIES.stream() + .anyMatch(keywordClass -> + keywordClass.isAssignableFrom(abilityClass) + ); } @Override diff --git a/Mage.Sets/src/mage/cards/c/CallForAid.java b/Mage.Sets/src/mage/cards/c/CallForAid.java index cfbcf2d5dd30..288d480ba48e 100644 --- a/Mage.Sets/src/mage/cards/c/CallForAid.java +++ b/Mage.Sets/src/mage/cards/c/CallForAid.java @@ -1,5 +1,6 @@ package mage.cards.c; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.OneShotEffect; @@ -153,13 +154,20 @@ public CallForAidYouCantSacrificeEffect copy() { } @Override - public boolean apply(Game game, Ability source) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + ((Permanent) object).setCanBeSacrificed(false); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game)) { if (permanent.getControllerId().equals(playerId)) { - permanent.setCanBeSacrificed(false); + affectedObjects.add(permanent); } } - return true; + return !affectedObjects.isEmpty(); } } diff --git a/Mage.Sets/src/mage/cards/c/CaptivatingVampire.java b/Mage.Sets/src/mage/cards/c/CaptivatingVampire.java index c2c1f3224e8c..2f8e6c92c973 100644 --- a/Mage.Sets/src/mage/cards/c/CaptivatingVampire.java +++ b/Mage.Sets/src/mage/cards/c/CaptivatingVampire.java @@ -1,6 +1,7 @@ package mage.cards.c; import mage.MageInt; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleStaticAbility; @@ -18,6 +19,8 @@ import mage.target.common.TargetControlledPermanent; import mage.target.common.TargetCreaturePermanent; +import java.util.ArrayList; +import java.util.List; import java.util.UUID; /** @@ -78,19 +81,25 @@ public CaptivatingVampireEffect copy() { } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); - if (permanent != null) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; switch (layer) { case ControlChangingEffects_2: - if (sublayer == SubLayer.NA) { - permanent.changeControllerId(source.getControllerId(), game, source); - } + permanent.changeControllerId(source.getControllerId(), game, source); break; case TypeChangingEffects_4: permanent.addSubType(game, SubType.VAMPIRE); break; } + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); + if (permanent != null) { + affectedObjects.add(permanent); return true; } discard(); @@ -98,7 +107,12 @@ public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) } @Override - public boolean apply(Game game, Ability source) { + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + List affectedObjects = new ArrayList<>(); + if (queryAffectedObjects(layer, source, game, affectedObjects)) { + applyToObjects(layer, sublayer, source, game, affectedObjects); + return true; + } return false; } diff --git a/Mage.Sets/src/mage/cards/c/CarnelianOrbOfDragonkind.java b/Mage.Sets/src/mage/cards/c/CarnelianOrbOfDragonkind.java index 1ab31d117e4c..128969f737b8 100644 --- a/Mage.Sets/src/mage/cards/c/CarnelianOrbOfDragonkind.java +++ b/Mage.Sets/src/mage/cards/c/CarnelianOrbOfDragonkind.java @@ -1,5 +1,6 @@ package mage.cards.c; +import mage.MageItem; import mage.MageObject; import mage.Mana; import mage.abilities.Ability; @@ -111,17 +112,23 @@ public CarnelianOrbOfDragonkindHasteEffect copy() { } @Override - public boolean apply(Game game, Ability source) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + ((Permanent) object).addAbility(HasteAbility.getInstance(), source.getSourceId(), game); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { CarnelianOrbOfDragonkindWatcher watcher = game.getState().getWatcher(CarnelianOrbOfDragonkindWatcher.class, source.getSourceId()); if (watcher == null) { return false; } - - for (Permanent perm : game.getBattlefield().getAllActivePermanents()) { - if (watcher.creatureCastWithOrbsMana(perm.getId())) { - perm.addAbility(HasteAbility.getInstance(), source.getSourceId(), game); + for (Permanent permanent : game.getBattlefield().getAllActivePermanents()) { + if (watcher.creatureCastWithOrbsMana(permanent.getId())) { + affectedObjects.add(permanent); } } - return true; + return !affectedObjects.isEmpty(); } } diff --git a/Mage.Sets/src/mage/cards/c/CaseOfTheUneatenFeast.java b/Mage.Sets/src/mage/cards/c/CaseOfTheUneatenFeast.java index 252bb31b6c43..aa5ee9636e22 100644 --- a/Mage.Sets/src/mage/cards/c/CaseOfTheUneatenFeast.java +++ b/Mage.Sets/src/mage/cards/c/CaseOfTheUneatenFeast.java @@ -1,5 +1,6 @@ package mage.cards.c; +import mage.MageItem; import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.common.CaseAbility; @@ -22,6 +23,7 @@ import mage.players.Player; import mage.watchers.common.PlayerGainedLifeWatcher; +import java.util.List; import java.util.Objects; import java.util.UUID; @@ -102,25 +104,30 @@ public void init(Ability source, Game game) { } @Override - public boolean apply(Game game, Ability source) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Card card = (Card) object; + MayCastFromGraveyardSourceAbility ability = new MayCastFromGraveyardSourceAbility(); + ability.setSourceId(card.getId()); + ability.setControllerId(card.getOwnerId()); + game.getState().addOtherAbility(card, ability); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Player player = game.getPlayer(source.getControllerId()); if (player == null) { return false; } - player.getGraveyard() - .stream() - .filter(cardId -> affectedObjectList.contains(new MageObjectReference(cardId, game))) - .forEach(cardId -> { - Card card = game.getCard(cardId); - if (card == null) { - return; - } - MayCastFromGraveyardSourceAbility ability = new MayCastFromGraveyardSourceAbility(); - ability.setSourceId(cardId); - ability.setControllerId(card.getOwnerId()); - game.getState().addOtherAbility(card, ability); - }); - return true; + for (MageObjectReference mor : affectedObjectList) { + Card card = mor.getCard(game); + if (card == null) { + continue; + } + affectedObjects.add(card); + } + return !affectedObjects.isEmpty(); } } diff --git a/Mage.Sets/src/mage/cards/c/CelestialDawn.java b/Mage.Sets/src/mage/cards/c/CelestialDawn.java index 397cf682d299..a6ea8f3490e4 100644 --- a/Mage.Sets/src/mage/cards/c/CelestialDawn.java +++ b/Mage.Sets/src/mage/cards/c/CelestialDawn.java @@ -1,5 +1,6 @@ package mage.cards.c; +import mage.MageItem; import mage.MageObject; import mage.ObjectColor; import mage.abilities.Ability; @@ -8,7 +9,6 @@ import mage.abilities.effects.AsThoughManaEffect; import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.mana.WhiteManaAbility; -import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; @@ -22,6 +22,7 @@ import mage.players.ManaPoolItem; import mage.players.Player; +import java.util.List; import java.util.UUID; /** @@ -61,7 +62,7 @@ class CelestialDawnToPlainsEffect extends ContinuousEffectImpl { private static final FilterLandPermanent filter = new FilterLandPermanent(); CelestialDawnToPlainsEffect() { - super(Duration.WhileOnBattlefield, Outcome.Detriment); + super(Duration.WhileOnBattlefield, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Detriment); this.staticText = "Lands you control are Plains"; } @@ -69,36 +70,29 @@ private CelestialDawnToPlainsEffect(final CelestialDawnToPlainsEffect effect) { super(effect); } - @Override - public boolean apply(Game game, Ability source) { - return false; - } - @Override public CelestialDawnToPlainsEffect copy() { return new CelestialDawnToPlainsEffect(this); } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - for (Permanent land : game.getBattlefield().getAllActivePermanents(filter, source.getControllerId(), game)) { - switch (layer) { - case AbilityAddingRemovingEffects_6: - land.removeAllAbilities(source.getSourceId(), game); - land.addAbility(new WhiteManaAbility(), source.getSourceId(), game); - break; - case TypeChangingEffects_4: - land.removeAllSubTypes(game, SubTypeSet.NonBasicLandType); - land.addSubType(game, SubType.PLAINS); - break; - } + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent land = (Permanent) object; + // 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.removeAllAbilities(source.getSourceId(), game); + land.removeAllSubTypes(game, SubTypeSet.NonBasicLandType); + land.addSubType(game, SubType.PLAINS); + land.addAbility(new WhiteManaAbility(), source.getSourceId(), game); } - return true; } @Override - public boolean hasLayer(Layer layer) { - return layer == Layer.AbilityAddingRemovingEffects_6 || layer == Layer.TypeChangingEffects_4; + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + affectedObjects.addAll(game.getBattlefield().getAllActivePermanents(filter, source.getControllerId(), game)); + return !affectedObjects.isEmpty(); } } @@ -113,56 +107,42 @@ public CelestialDawnToWhiteEffect() { } @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - for (Permanent perm : game.getBattlefield().getAllActivePermanents(filter, source.getControllerId(), game)) { - setColor(perm.getColor(game), game); - } - // Stack - for (MageObject object : game.getStack()) { - if (object instanceof Spell && ((Spell) object).isControlledBy(controller.getId())) { - setColor(object.getColor(game), game); - } - } - // Exile - for (Card card : game.getExile().getAllCards(game)) { - if (card.isOwnedBy(controller.getId())) { - setColor(card.getColor(game), game); - } - } - // Command - for (CommandObject commandObject : game.getState().getCommand()) { - if (commandObject instanceof Commander) { - if (commandObject.isControlledBy(controller.getId())) { - setColor(commandObject.getColor(game), game); - } - } - } + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + ((MageObject) object).getColor(game).setColor(ObjectColor.WHITE); + } + } - // Hand - for (Card card : controller.getHand().getCards(game)) { - setColor(card.getColor(game), game); - } - // Library - for (Card card : controller.getLibrary().getCards(game)) { - setColor(card.getColor(game), game); + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return false; + } + // Battlefield + affectedObjects.addAll(game.getBattlefield().getAllActivePermanents(filter, source.getControllerId(), game)); + // Stack + for (MageObject object : game.getStack()) { + if (object instanceof Spell && ((Spell) object).isControlledBy(controller.getId())) { + affectedObjects.add(object); } - // Graveyard - for (Card card : controller.getGraveyard().getCards(game)) { - setColor(card.getColor(game), game); + } + // Exile + affectedObjects.addAll(game.getExile().getAllCards(game, controller.getId())); + // Command + for (CommandObject commandObject : game.getState().getCommand()) { + if (commandObject instanceof Commander && commandObject.isControlledBy(controller.getId())) { + affectedObjects.add(commandObject); } - return true; } - return false; - } - - protected static void setColor(ObjectColor color, Game game) { - color.setWhite(true); - color.setGreen(false); - color.setBlue(false); - color.setBlack(false); - color.setRed(false); + // Hand + affectedObjects.addAll(controller.getHand().getCards(game)); + // Library + affectedObjects.addAll(controller.getLibrary().getCards(game)); + // Graveyard + affectedObjects.addAll(controller.getGraveyard().getCards(game)); + + return !affectedObjects.isEmpty(); } @Override diff --git a/Mage.Sets/src/mage/cards/c/ChallengerTroll.java b/Mage.Sets/src/mage/cards/c/ChallengerTroll.java index 009c88a411dd..692ae897b3d4 100644 --- a/Mage.Sets/src/mage/cards/c/ChallengerTroll.java +++ b/Mage.Sets/src/mage/cards/c/ChallengerTroll.java @@ -1,14 +1,16 @@ package mage.cards.c; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.common.combat.CantBeBlockedByMoreThanOneAllEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; -import mage.game.Game; -import mage.game.permanent.Permanent; +import mage.constants.CardType; +import mage.constants.ComparisonType; +import mage.constants.SubType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.mageobject.PowerPredicate; import java.util.UUID; @@ -17,6 +19,13 @@ */ public final class ChallengerTroll extends CardImpl { + private static final FilterPermanent filter = new FilterControlledCreaturePermanent(); + + static { + filter.add(new PowerPredicate(ComparisonType.OR_GREATER, 4)); + } + + public ChallengerTroll(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{G}"); @@ -25,7 +34,7 @@ public ChallengerTroll(UUID ownerId, CardSetInfo setInfo) { this.toughness = new MageInt(5); // Each creature you control with power 4 or greater can't be blocked by more than one creature. - this.addAbility(new SimpleStaticAbility(new ChallengerTrollEffect())); + this.addAbility(new SimpleStaticAbility(new CantBeBlockedByMoreThanOneAllEffect(filter))); } private ChallengerTroll(final ChallengerTroll card) { @@ -37,44 +46,3 @@ public ChallengerTroll copy() { return new ChallengerTroll(this); } } - -class ChallengerTrollEffect extends ContinuousEffectImpl { - - ChallengerTrollEffect() { - super(Duration.WhileOnBattlefield, Outcome.Benefit); - staticText = "Each creature you control with power 4 or greater can't be blocked by more than one creature."; - } - - private ChallengerTrollEffect(final ChallengerTrollEffect effect) { - super(effect); - } - - @Override - public ChallengerTrollEffect copy() { - return new ChallengerTrollEffect(this); - } - - @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - if (layer != Layer.RulesEffects) { - return false; - } - for (Permanent permanent : game.getBattlefield().getActivePermanents(source.getControllerId(), game)) { - if (permanent != null && permanent.isControlledBy(source.getControllerId()) - && permanent.isCreature(game) && permanent.getPower().getValue() >= 4) { - permanent.setMaxBlockedBy(1); - } - } - return true; - } - - @Override - public boolean apply(Game game, Ability source) { - return false; - } - - @Override - public boolean hasLayer(Layer layer) { - return layer == Layer.RulesEffects; - } -} diff --git a/Mage.Sets/src/mage/cards/c/ChariotOfTheSun.java b/Mage.Sets/src/mage/cards/c/ChariotOfTheSun.java index ce2056672afc..b4297ee232a4 100644 --- a/Mage.Sets/src/mage/cards/c/ChariotOfTheSun.java +++ b/Mage.Sets/src/mage/cards/c/ChariotOfTheSun.java @@ -1,6 +1,6 @@ package mage.cards.c; -import java.util.UUID; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapSourceCost; @@ -10,15 +10,14 @@ import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Layer; -import mage.constants.Outcome; -import mage.constants.SubLayer; +import mage.constants.*; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.common.TargetControlledCreaturePermanent; +import java.util.List; +import java.util.UUID; + /** * * @author TheElk801 @@ -70,13 +69,21 @@ public ChariotOfTheSunEffect copy() { } @Override - public boolean apply(Game game, Ability source) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; + permanent.getToughness().setModifiedBaseValue(1); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); if (permanent == null) { this.discard(); return false; } - permanent.getToughness().setModifiedBaseValue(1); + affectedObjects.add(permanent); return true; } } diff --git a/Mage.Sets/src/mage/cards/c/ChimericCoils.java b/Mage.Sets/src/mage/cards/c/ChimericCoils.java index 764a0b4ac988..8fb3cd572b6b 100644 --- a/Mage.Sets/src/mage/cards/c/ChimericCoils.java +++ b/Mage.Sets/src/mage/cards/c/ChimericCoils.java @@ -4,15 +4,13 @@ import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; import mage.abilities.effects.common.SacrificeSourceEffect; +import mage.abilities.effects.common.continuous.BecomesXXConstructSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.util.CardUtil; +import mage.constants.CardType; +import mage.constants.Duration; import java.util.UUID; @@ -25,7 +23,7 @@ public ChimericCoils(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}"); // {X}{1}: Chimeric Coils becomes an X/X Construct artifact creature. Sacrifice it at the beginning of the next end step. - Ability ability = new SimpleActivatedAbility(new ChimericCoilsEffect(), new ManaCostsImpl<>("{X}{1}")); + Ability ability = new SimpleActivatedAbility(new BecomesXXConstructSourceEffect(Duration.Custom), new ManaCostsImpl<>("{X}{1}")); ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new SacrificeSourceEffect()))); this.addAbility(ability); } @@ -39,58 +37,3 @@ public ChimericCoils copy() { return new ChimericCoils(this); } } - -class ChimericCoilsEffect extends ContinuousEffectImpl { - - ChimericCoilsEffect() { - super(Duration.Custom, Outcome.BecomeCreature); - staticText = "{this} becomes an X/X Construct artifact creature"; - this.dependencyTypes.add(DependencyType.BecomeCreature); - } - - private ChimericCoilsEffect(final ChimericCoilsEffect effect) { - super(effect); - } - - @Override - public ChimericCoilsEffect copy() { - return new ChimericCoilsEffect(this); - } - - @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent == null) { - return false; - } - switch (layer) { - case TypeChangingEffects_4: - if (!permanent.isArtifact(game)) { - permanent.addCardType(game, CardType.ARTIFACT); - } - if (!permanent.isCreature(game)) { - permanent.addCardType(game, CardType.CREATURE); - } - permanent.removeAllCreatureTypes(game); - permanent.addSubType(game, SubType.CONSTRUCT); - break; - case PTChangingEffects_7: - if (sublayer == SubLayer.SetPT_7b) { - int xValue = CardUtil.getSourceCostsTag(game, source, "X", 0); - permanent.getPower().setModifiedBaseValue(xValue); - permanent.getToughness().setModifiedBaseValue(xValue); - } - } - 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; - } -} diff --git a/Mage.Sets/src/mage/cards/c/ChimericStaff.java b/Mage.Sets/src/mage/cards/c/ChimericStaff.java index ac323495b8f9..f124f1818d32 100644 --- a/Mage.Sets/src/mage/cards/c/ChimericStaff.java +++ b/Mage.Sets/src/mage/cards/c/ChimericStaff.java @@ -1,15 +1,11 @@ package mage.cards.c; -import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.common.continuous.BecomesXXConstructSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.util.CardUtil; import java.util.UUID; @@ -22,7 +18,7 @@ public ChimericStaff(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}"); // {X}: Chimeric Staff becomes an X/X Construct artifact creature until end of turn. - this.addAbility(new SimpleActivatedAbility(new ChimericStaffEffect(), new ManaCostsImpl<>("{X}"))); + this.addAbility(new SimpleActivatedAbility(new BecomesXXConstructSourceEffect(Duration.EndOfTurn), new ManaCostsImpl<>("{X}"))); } private ChimericStaff(final ChimericStaff card) { @@ -34,58 +30,3 @@ public ChimericStaff copy() { return new ChimericStaff(this); } } - -class ChimericStaffEffect extends ContinuousEffectImpl { - - ChimericStaffEffect() { - super(Duration.EndOfTurn, Outcome.BecomeCreature); - staticText = "{this} becomes an X/X Construct artifact creature until end of turn"; - this.dependencyTypes.add(DependencyType.BecomeCreature); - } - - private ChimericStaffEffect(final ChimericStaffEffect effect) { - super(effect); - } - - @Override - public ChimericStaffEffect copy() { - return new ChimericStaffEffect(this); - } - - @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent == null) { - return false; - } - switch (layer) { - case TypeChangingEffects_4: - if (!permanent.isArtifact(game)) { - permanent.addCardType(game, CardType.ARTIFACT); - } - if (!permanent.isCreature(game)) { - permanent.addCardType(game, CardType.CREATURE); - } - permanent.removeAllCreatureTypes(game); - permanent.addSubType(game, SubType.CONSTRUCT); - break; - case PTChangingEffects_7: - if (sublayer == SubLayer.SetPT_7b) { - int xValue = CardUtil.getSourceCostsTag(game, source, "X", 0); - permanent.getPower().setModifiedBaseValue(xValue); - permanent.getToughness().setModifiedBaseValue(xValue); - } - } - 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; - } -} diff --git a/Mage.Sets/src/mage/cards/c/ChirrutImwe.java b/Mage.Sets/src/mage/cards/c/ChirrutImwe.java index 2e8be6534fe9..20674e1ec846 100644 --- a/Mage.Sets/src/mage/cards/c/ChirrutImwe.java +++ b/Mage.Sets/src/mage/cards/c/ChirrutImwe.java @@ -1,6 +1,7 @@ package mage.cards.c; import mage.MageInt; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleStaticAbility; @@ -14,6 +15,7 @@ import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.List; import java.util.UUID; /** @@ -52,7 +54,7 @@ public ChirrutImwe copy() { class ChirrutImweEffect extends ContinuousEffectImpl { public ChirrutImweEffect() { - super(Duration.WhileOnBattlefield, Outcome.Benefit); + super(Duration.WhileOnBattlefield, Layer.RulesEffects, SubLayer.NA, Outcome.Benefit); staticText = "{this} can block up to two additional creatures"; } @@ -66,28 +68,21 @@ public ChirrutImweEffect copy() { } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - Permanent perm = game.getPermanent(source.getSourceId()); - if (perm != null) { - switch (layer) { - case RulesEffects: - // maxBlocks = 0 equals to "can block any number of creatures" - if (perm.getMaxBlocks() > 0) { - perm.setMaxBlocks(perm.getMaxBlocks() + 2); - } - break; - } + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; + permanent.setMaxBlocks(permanent.getMaxBlocks() + 2); } - return false; } @Override - public boolean apply(Game game, Ability source) { - return false; - } - - @Override - public boolean hasLayer(Layer layer) { - return layer == Layer.RulesEffects; + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + Permanent permanent = game.getPermanent(source.getSourceId()); + // maxBlocks = 0 equals to "can block any number of creatures" + if (permanent == null || permanent.getMaxBlocks() == 0) { + return false; + } + affectedObjects.add(permanent); + return true; } } diff --git a/Mage.Sets/src/mage/cards/c/ChissGoriaForgeTyrant.java b/Mage.Sets/src/mage/cards/c/ChissGoriaForgeTyrant.java index 6eca6368d9e5..52353debad01 100644 --- a/Mage.Sets/src/mage/cards/c/ChissGoriaForgeTyrant.java +++ b/Mage.Sets/src/mage/cards/c/ChissGoriaForgeTyrant.java @@ -1,6 +1,7 @@ package mage.cards.c; import mage.MageInt; +import mage.MageItem; import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; @@ -158,25 +159,33 @@ public ChissGoriaForgeTyrantAffinityEffect copy() { } @Override - public boolean apply(Game game, Ability source) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + game.getState().addOtherAbility((Card) object, new AffinityForArtifactsAbility()); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { if (!ChissGoriaForgeTyrantWatcher.checkRef(source, morSet, game)) { discard(); return false; } - for (Card card : game.getExile().getAllCardsByRange(game, source.getControllerId())) { - if (morSet.contains(new MageObjectReference(card, game)) && card.isArtifact(game)) { - game.getState().addOtherAbility(card, new AffinityForArtifactsAbility()); + for (MageObjectReference mor : morSet) { + Card card = mor.getCard(game); + if (card != null && card.isArtifact(game)) { + affectedObjects.add(card); } } for (StackObject stackObject : game.getStack()) { - if (!(stackObject instanceof Spell) || !stackObject.isControlledBy(source.getControllerId())) { + if (!(stackObject instanceof Spell) || !stackObject.isControlledBy(source.getControllerId())) { continue; } Card card = game.getCard(stackObject.getSourceId()); if (card != null && morSet.contains(new MageObjectReference(card, game, -1))) { - game.getState().addOtherAbility(card, new AffinityForArtifactsAbility()); + affectedObjects.add(card); } } return true; diff --git a/Mage.Sets/src/mage/cards/c/CircleOfTheMoonDruid.java b/Mage.Sets/src/mage/cards/c/CircleOfTheMoonDruid.java index 11b3632e532e..fcbeb2ab7dc2 100644 --- a/Mage.Sets/src/mage/cards/c/CircleOfTheMoonDruid.java +++ b/Mage.Sets/src/mage/cards/c/CircleOfTheMoonDruid.java @@ -1,6 +1,7 @@ package mage.cards.c; import mage.MageInt; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousEffectImpl; @@ -10,6 +11,8 @@ import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.ArrayList; +import java.util.List; import java.util.UUID; /** @@ -56,29 +59,43 @@ public CircleOfTheMoonDruidBearEffect copy() { return new CircleOfTheMoonDruidBearEffect(this); } + @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; + switch (layer) { + case TypeChangingEffects_4: + permanent.removeAllCreatureTypes(game); + permanent.addSubType(game, SubType.BEAR); + break; + case PTChangingEffects_7: + if (sublayer == SubLayer.SetPT_7b) { + permanent.getPower().setModifiedBaseValue(4); + permanent.getToughness().setModifiedBaseValue(2); + } + break; + } + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Permanent permanent = source.getSourcePermanentIfItStillExists(game); if (permanent == null || !game.isActivePlayer(source.getControllerId())) { return false; } - switch (layer) { - case TypeChangingEffects_4: - permanent.removeAllCreatureTypes(game); - permanent.addSubType(game, SubType.BEAR); - return true; - case PTChangingEffects_7: - if (sublayer == SubLayer.SetPT_7b) { - permanent.getPower().setModifiedBaseValue(4); - permanent.getToughness().setModifiedBaseValue(2); - return true; - } - } - return false; + affectedObjects.add(permanent); + return true; } @Override - public boolean apply(Game game, Ability source) { + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + List affectedObjects = new ArrayList<>(); + if (queryAffectedObjects(layer, source, game, affectedObjects)) { + applyToObjects(layer, sublayer, source, game, affectedObjects); + return true; + } return false; } diff --git a/Mage.Sets/src/mage/cards/c/Clamavus.java b/Mage.Sets/src/mage/cards/c/Clamavus.java index f72aadc96236..2d05983076bf 100644 --- a/Mage.Sets/src/mage/cards/c/Clamavus.java +++ b/Mage.Sets/src/mage/cards/c/Clamavus.java @@ -1,6 +1,7 @@ package mage.cards.c; import mage.MageInt; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousEffectImpl; @@ -60,17 +61,23 @@ public ClamavusEffect copy() { } @Override - public boolean apply(Game game, Ability source) { - List permanents = game.getBattlefield().getActivePermanents( - StaticFilters.FILTER_CONTROLLED_CREATURE, source.getControllerId(), game - ); - for (Permanent permanent : permanents) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; int count = permanent.getCounters(game).getCount(CounterType.P1P1); - if (count > 0) { - permanent.addPower(count); - permanent.addToughness(count); + permanent.addPower(count); + permanent.addToughness(count); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + for (Permanent permanent : game.getBattlefield().getActivePermanents( + StaticFilters.FILTER_CONTROLLED_CREATURE, source.getControllerId(), game)) { + if (permanent.getCounters(game).getCount(CounterType.P1P1) > 0) { + affectedObjects.add(permanent); } } - return true; + return !affectedObjects.isEmpty(); } } diff --git a/Mage.Sets/src/mage/cards/c/CoatOfArms.java b/Mage.Sets/src/mage/cards/c/CoatOfArms.java index 26b8c76254a7..6e3ee79a3998 100644 --- a/Mage.Sets/src/mage/cards/c/CoatOfArms.java +++ b/Mage.Sets/src/mage/cards/c/CoatOfArms.java @@ -1,6 +1,7 @@ package mage.cards.c; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousEffectImpl; @@ -53,22 +54,26 @@ public CoatOfArmsEffect copy() { } @Override - public boolean apply(Game game, Ability source) { - List permanents = game.getBattlefield().getActivePermanents( - StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), game - ); - for (Permanent permanent : permanents) { - int amount = getAmount(permanents, permanent, game); + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; + int amount = getAmount(affectedObjects, permanent, game); permanent.addPower(amount); permanent.addToughness(amount); } - return true; } - private int getAmount(List permanents, Permanent target, Game game) { + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + affectedObjects.addAll(game.getBattlefield().getActivePermanents( + StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), game)); + return !affectedObjects.isEmpty(); + } + + private int getAmount(List permanents, Permanent target, Game game) { int amount = 0; - for (Permanent permanent : permanents) { - if (!permanent.getId().equals(target.getId()) && permanent.shareCreatureTypes(game, target)) { + for (MageItem permanent : permanents) { + if (!permanent.getId().equals(target.getId()) && ((Permanent) permanent).shareCreatureTypes(game, target)) { amount++; } } diff --git a/Mage.Sets/src/mage/cards/c/CometStellarPup.java b/Mage.Sets/src/mage/cards/c/CometStellarPup.java index e534188ebb44..70943e564f30 100644 --- a/Mage.Sets/src/mage/cards/c/CometStellarPup.java +++ b/Mage.Sets/src/mage/cards/c/CometStellarPup.java @@ -1,5 +1,6 @@ package mage.cards.c; +import mage.MageItem; import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.LoyaltyAbility; @@ -29,6 +30,7 @@ import mage.target.targetpointer.FixedTarget; import mage.target.targetpointer.FixedTargets; +import java.util.List; import java.util.UUID; /** @@ -177,11 +179,20 @@ public CometStellarPupContinuousEffect copy() { } @Override - public boolean apply(Game game, Ability source) { - Permanent comet = cometMOR.getPermanent(game); - if (comet != null) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent comet = (Permanent) object; comet.incrementLoyaltyActivationsAvailable(); comet.incrementLoyaltyActivationsAvailable(); + + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + Permanent comet = cometMOR.getPermanent(game); + if (comet != null) { + affectedObjects.add(comet); return true; } return false; diff --git a/Mage.Sets/src/mage/cards/c/CommandersPlate.java b/Mage.Sets/src/mage/cards/c/CommandersPlate.java index 6a04a1c38b5f..2213329b1ec8 100644 --- a/Mage.Sets/src/mage/cards/c/CommandersPlate.java +++ b/Mage.Sets/src/mage/cards/c/CommandersPlate.java @@ -1,5 +1,6 @@ package mage.cards.c; +import mage.MageItem; import mage.ObjectColor; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; @@ -23,6 +24,7 @@ import mage.target.common.TargetControlledCreaturePermanent; import mage.target.targetpointer.FixedTarget; +import java.util.List; import java.util.Set; import java.util.UUID; @@ -100,7 +102,40 @@ public void init(Ability source, Game game) { } @Override - public boolean apply(Game game, Ability source) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + Player player = game.getPlayer(source.getControllerId()); + Set commanders = game.getCommandersIds(player, CommanderCardType.COMMANDER_OR_OATHBREAKER, false); + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; + ObjectColor color = new ObjectColor("WUBRG"); + for (UUID commanderId : commanders) { + Card card = game.getCard(commanderId); + if (card == null) { + continue; + } + FilterMana identity = card.getColorIdentity(); + if (identity.isWhite()) { + color.setWhite(false); + } + if (identity.isBlue()) { + color.setBlue(false); + } + if (identity.isBlack()) { + color.setBlack(false); + } + if (identity.isRed()) { + color.setRed(false); + } + if (identity.isGreen()) { + color.setGreen(false); + } + } + permanent.addAbility(ProtectionAbility.from(color), source.getSourceId(), game); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Player player = game.getPlayer(source.getControllerId()); if (player == null) { return false; @@ -119,35 +154,10 @@ public boolean apply(Game game, Ability source) { } } Set commanders = game.getCommandersIds(player, CommanderCardType.COMMANDER_OR_OATHBREAKER, false); - if (commanders.isEmpty()) { + if (commanders.isEmpty() || permanent == null) { return false; } - ObjectColor color = new ObjectColor("WUBRG"); - for (UUID commanderId : commanders) { - Card card = game.getCard(commanderId); - if (card == null) { - continue; - } - FilterMana identity = card.getColorIdentity(); - if (identity.isWhite()) { - color.setWhite(false); - } - if (identity.isBlue()) { - color.setBlue(false); - } - if (identity.isBlack()) { - color.setBlack(false); - } - if (identity.isRed()) { - color.setRed(false); - } - if (identity.isGreen()) { - color.setGreen(false); - } - } - if (permanent != null) { - permanent.addAbility(ProtectionAbility.from(color), source.getSourceId(), game); - } + affectedObjects.add(permanent); return true; } } diff --git a/Mage.Sets/src/mage/cards/c/ConfessionDial.java b/Mage.Sets/src/mage/cards/c/ConfessionDial.java index 4b7ddf5228dc..245492e7b3fb 100644 --- a/Mage.Sets/src/mage/cards/c/ConfessionDial.java +++ b/Mage.Sets/src/mage/cards/c/ConfessionDial.java @@ -1,7 +1,6 @@ package mage.cards.c; -import java.util.UUID; - +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; @@ -17,6 +16,9 @@ import mage.game.Game; import mage.target.common.TargetCardInYourGraveyard; +import java.util.List; +import java.util.UUID; + /** * @author Cguy7777 */ @@ -66,15 +68,23 @@ private ConfessionDialEffect(final ConfessionDialEffect effect) { } @Override - public boolean apply(Game game, Ability source) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Card card = (Card) object; + Ability ability = new EscapeAbility(card, card.getManaCost().getText(), 3); + ability.setSourceId(card.getId()); + ability.setControllerId(card.getOwnerId()); + game.getState().addOtherAbility(card, ability); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Card card = game.getCard(getTargetPointer().getFirst(game, source)); if (card == null || card.getManaCost().getText().isEmpty()) { return false; } - Ability ability = new EscapeAbility(card, card.getManaCost().getText(), 3); - ability.setSourceId(card.getId()); - ability.setControllerId(card.getOwnerId()); - game.getState().addOtherAbility(card, ability); + affectedObjects.add(card); return true; } diff --git a/Mage.Sets/src/mage/cards/c/Conspiracy.java b/Mage.Sets/src/mage/cards/c/Conspiracy.java index c05affa5d3b7..4bc2f3aa31c3 100644 --- a/Mage.Sets/src/mage/cards/c/Conspiracy.java +++ b/Mage.Sets/src/mage/cards/c/Conspiracy.java @@ -1,5 +1,6 @@ package mage.cards.c; +import mage.MageItem; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.AsEntersBattlefieldAbility; @@ -19,7 +20,6 @@ import mage.players.Player; import mage.util.SubTypes; -import java.util.Iterator; import java.util.List; import java.util.UUID; @@ -70,7 +70,21 @@ public ConspiracyEffect copy() { } @Override - public boolean apply(Game game, Ability source) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + SubType subType = ChooseCreatureTypeEffect.getChosenCreatureType(source.getSourceId(), game); + for (MageItem object : affectedObjects) { + if (object instanceof Permanent) { + Permanent permanent = (Permanent) object; + permanent.removeAllSubTypes(game); + permanent.addSubType(game, subType); + } else { + setCreatureSubtype((MageObject) object, subType, game); + } + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Player controller = game.getPlayer(source.getControllerId()); SubType subType = ChooseCreatureTypeEffect.getChosenCreatureType(source.getSourceId(), game); if (controller == null || subType == null) { @@ -81,56 +95,54 @@ public boolean apply(Game game, Ability source) { for (UUID cardId : controller.getGraveyard()) { Card card = game.getCard(cardId); if (card != null && card.isCreature(game)) { - setCreatureSubtype(card, subType, game); + affectedObjects.add(card); } } // on Hand for (UUID cardId : controller.getHand()) { Card card = game.getCard(cardId); if (card != null && card.isCreature(game)) { - setCreatureSubtype(card, subType, game); + affectedObjects.add(card); } } // in Exile - for (Card card : game.getState().getExile().getAllCards(game)) { + for (Card card : game.getState().getExile().getAllCards(game, controller.getId())) { if (card.isOwnedBy(controller.getId()) && card.isCreature(game)) { - setCreatureSubtype(card, subType, game); + affectedObjects.add(card); } } // in Library (e.g. for Mystical Teachings) for (Card card : controller.getLibrary().getCards(game)) { if (card.isOwnedBy(controller.getId()) && card.isCreature(game)) { - setCreatureSubtype(card, subType, game); + affectedObjects.add(card); } } // in command zone for (CommandObject commandObject : game.getState().getCommand()) { if (commandObject instanceof Commander) { - Card card = game.getCard(((Commander) commandObject).getId()); + Card card = game.getCard(commandObject.getId()); if (card != null && card.isCreature(game) && card.isOwnedBy(controller.getId())) { - setCreatureSubtype(card, subType, game); + affectedObjects.add(card); } } } // creature spells you control - for (Iterator iterator = game.getStack().iterator(); iterator.hasNext(); ) { - StackObject stackObject = iterator.next(); + for (StackObject stackObject : game.getStack()) { if (stackObject instanceof Spell && stackObject.isControlledBy(controller.getId()) && stackObject.isCreature(game)) { - setCreatureSubtype(stackObject, subType, game); - setCreatureSubtype(((Spell) stackObject).getCard(), subType, game); + affectedObjects.add(stackObject); + affectedObjects.add(((Spell) stackObject).getCard()); } } // creatures you control List permanents = game.getBattlefield().getAllActivePermanents(controller.getId()); for (Permanent permanent : permanents) { if (permanent.isCreature(game)) { - permanent.removeAllCreatureTypes(game); - permanent.addSubType(game, subType); + affectedObjects.add(permanent); } } - return true; + return !affectedObjects.isEmpty(); } private void setCreatureSubtype(MageObject object, SubType subtype, Game game) { @@ -143,4 +155,5 @@ private void setCreatureSubtype(MageObject object, SubType subtype, Game game) { subTypes.add(subtype); } } + } diff --git a/Mage.Sets/src/mage/cards/c/ConspiracyUnraveler.java b/Mage.Sets/src/mage/cards/c/ConspiracyUnraveler.java index 0804a14dfbab..73222903d41b 100644 --- a/Mage.Sets/src/mage/cards/c/ConspiracyUnraveler.java +++ b/Mage.Sets/src/mage/cards/c/ConspiracyUnraveler.java @@ -1,6 +1,7 @@ package mage.cards.c; import mage.MageInt; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.SourceIsSpellCondition; @@ -14,6 +15,7 @@ import mage.game.Game; import mage.players.Player; +import java.util.List; import java.util.UUID; /** @@ -52,7 +54,7 @@ class ConspiracyUnravelerInsteadEffect extends ContinuousEffectImpl { private final AlternativeCostSourceAbility alternativeCastingCostAbility = new AlternativeCostSourceAbility(new CollectEvidenceCost(10), SourceIsSpellCondition.instance); ConspiracyUnravelerInsteadEffect() { - super(Duration.WhileOnBattlefield, Outcome.Detriment); + super(Duration.WhileOnBattlefield, Layer.RulesEffects, SubLayer.NA, Outcome.Detriment); staticText = "You may collect evidence 10 rather than pay the mana cost for spells that you cast"; } @@ -72,23 +74,20 @@ public void init(Ability source, Game game, UUID activePlayerId) { } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - controller.getAlternativeSourceCosts().add(alternativeCastingCostAbility); - return true; + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + ((Player) object).getAlternativeSourceCosts().add(alternativeCastingCostAbility); } - return false; } @Override - public boolean apply(Game game, Ability source) { + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + affectedObjects.add(controller); + return true; + } return false; } - @Override - public boolean hasLayer(Layer layer) { - return layer == Layer.RulesEffects; - } - } diff --git a/Mage.Sets/src/mage/cards/c/Conversion.java b/Mage.Sets/src/mage/cards/c/Conversion.java index 73afd85c63a9..edad79cd3aec 100644 --- a/Mage.Sets/src/mage/cards/c/Conversion.java +++ b/Mage.Sets/src/mage/cards/c/Conversion.java @@ -1,7 +1,7 @@ package mage.cards.c; +import mage.MageItem; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.ContinuousEffect; @@ -9,10 +9,11 @@ import mage.abilities.effects.Effect; import mage.abilities.effects.common.SacrificeSourceUnlessPaysEffect; import mage.abilities.mana.WhiteManaAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; -import mage.filter.StaticFilters; +import mage.filter.common.FilterLandPermanent; import mage.game.Game; import mage.game.permanent.Permanent; @@ -52,7 +53,7 @@ public Conversion copy() { static class ConversionEffect extends ContinuousEffectImpl { ConversionEffect() { - super(Duration.WhileOnBattlefield, Outcome.Detriment); + super(Duration.WhileOnBattlefield, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Detriment); this.staticText = "All Mountains are Plains"; } @@ -60,36 +61,27 @@ private ConversionEffect(final ConversionEffect effect) { super(effect); } - @Override - public boolean apply(Game game, Ability source) { - return false; - } - @Override public ConversionEffect copy() { return new ConversionEffect(this); } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - for (Permanent land : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_LAND, source.getControllerId(), source, game)) { - switch (layer) { - case TypeChangingEffects_4: - if (land.hasSubtype(SubType.MOUNTAIN, game)) { - land.removeAllSubTypes(game, SubTypeSet.NonBasicLandType); - land.addSubType(game, SubType.PLAINS); - land.removeAllAbilities(source.getSourceId(), game); - land.addAbility(new WhiteManaAbility(), source.getSourceId(), game); - break; - } - } + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent land = (Permanent) object; + land.removeAllSubTypes(game, SubTypeSet.NonBasicLandType); + land.addSubType(game, SubType.PLAINS); + land.removeAllAbilities(source.getSourceId(), game); + land.addAbility(new WhiteManaAbility(), source.getSourceId(), game); } - return true; } @Override - public boolean hasLayer(Layer layer) { - return layer == Layer.TypeChangingEffects_4; + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + affectedObjects.addAll(game.getBattlefield().getActivePermanents( + new FilterLandPermanent(SubType.MOUNTAIN, "Mountains"), source.getControllerId(), source, game)); + return !affectedObjects.isEmpty(); } @Override diff --git a/Mage.Sets/src/mage/cards/c/ConvincingMirage.java b/Mage.Sets/src/mage/cards/c/ConvincingMirage.java index 08674d28a6a7..919f7abcfd4e 100644 --- a/Mage.Sets/src/mage/cards/c/ConvincingMirage.java +++ b/Mage.Sets/src/mage/cards/c/ConvincingMirage.java @@ -1,5 +1,6 @@ package mage.cards.c; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.SimpleStaticAbility; @@ -16,6 +17,7 @@ import mage.target.TargetPermanent; import mage.target.common.TargetLandPermanent; +import java.util.List; import java.util.UUID; /** @@ -96,7 +98,35 @@ public void init(Ability source, Game game) { } @Override - public boolean apply(Game game, Ability source) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + SubType choice = SubType.byDescription((String) game.getState().getValue(source.getSourceId().toString() + ChooseBasicLandTypeEffect.VALUE_KEY)); + for (MageItem object : affectedObjects) { + Permanent land = (Permanent) object; + land.removeAllSubTypes(game, SubTypeSet.NonBasicLandType); + land.addSubType(game, choice); + land.removeAllAbilities(source.getSourceId(), game); + switch (choice) { + case FOREST: + land.addAbility(new GreenManaAbility(), source.getSourceId(), game); + break; + case PLAINS: + land.addAbility(new WhiteManaAbility(), source.getSourceId(), game); + break; + case MOUNTAIN: + land.addAbility(new RedManaAbility(), source.getSourceId(), game); + break; + case ISLAND: + land.addAbility(new BlueManaAbility(), source.getSourceId(), game); + break; + case SWAMP: + land.addAbility(new BlackManaAbility(), source.getSourceId(), game); + break; + } + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { 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) { @@ -106,26 +136,7 @@ public boolean apply(Game game, Ability source) { if (land == null) { return false; } - land.removeAllSubTypes(game, SubTypeSet.NonBasicLandType); - land.addSubType(game, choice); - land.removeAllAbilities(source.getSourceId(), game); - switch (choice) { - case FOREST: - land.addAbility(new GreenManaAbility(), source.getSourceId(), game); - break; - case PLAINS: - land.addAbility(new WhiteManaAbility(), source.getSourceId(), game); - break; - case MOUNTAIN: - land.addAbility(new RedManaAbility(), source.getSourceId(), game); - break; - case ISLAND: - land.addAbility(new BlueManaAbility(), source.getSourceId(), game); - break; - case SWAMP: - land.addAbility(new BlackManaAbility(), source.getSourceId(), game); - break; - } + affectedObjects.add(land); return true; } } diff --git a/Mage.Sets/src/mage/cards/c/CosimaGodOfTheVoyage.java b/Mage.Sets/src/mage/cards/c/CosimaGodOfTheVoyage.java index 55dba3ec118a..c8456517828c 100644 --- a/Mage.Sets/src/mage/cards/c/CosimaGodOfTheVoyage.java +++ b/Mage.Sets/src/mage/cards/c/CosimaGodOfTheVoyage.java @@ -1,15 +1,16 @@ package mage.cards.c; import mage.MageInt; +import mage.MageItem; import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.DealsDamageToAPlayerAllTriggeredAbility; import mage.abilities.effects.AsThoughEffectImpl; import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.OneShotEffect; import mage.abilities.keyword.CrewAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.*; import mage.constants.*; import mage.counters.CounterType; @@ -21,6 +22,7 @@ import mage.players.Player; import java.util.HashSet; +import java.util.List; import java.util.Set; import java.util.UUID; import java.util.stream.Collectors; @@ -136,17 +138,25 @@ public CosimaGodOfTheVoyageGainAbilityEffect copy() { } @Override - public boolean apply(Game game, Ability source) { - Card card = mor.getCard(game); - if (card != null && game.getState().getZone(card.getId()) == Zone.EXILED) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Card card = (Card) object; Ability ability = new CosimaGodOfTheVoyageTriggeredAbility(); ability.setSourceId(card.getId()); ability.setControllerId(source.getControllerId()); game.getState().addOtherAbility(card, ability); - } else { - discard(); } - return true; + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + Card card = mor.getCard(game); + if (card != null && game.getState().getZone(card.getId()) == Zone.EXILED) { + affectedObjects.add(card); + return true; + } + discard(); + return false; } } diff --git a/Mage.Sets/src/mage/cards/c/CourageousResolve.java b/Mage.Sets/src/mage/cards/c/CourageousResolve.java index b3719ad81815..f0795242b8a1 100644 --- a/Mage.Sets/src/mage/cards/c/CourageousResolve.java +++ b/Mage.Sets/src/mage/cards/c/CourageousResolve.java @@ -1,5 +1,6 @@ package mage.cards.c; +import mage.MageItem; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.condition.common.FatefulHourCondition; @@ -25,6 +26,7 @@ import mage.target.common.TargetControlledCreaturePermanent; import java.util.HashSet; +import java.util.List; import java.util.Set; import java.util.UUID; @@ -145,10 +147,17 @@ public CourageousResolveCantLoseLifeEffect copy() { } @Override - public boolean apply(Game game, Ability source) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + ((Player) object).setCanLoseLife(false); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Player player = game.getPlayer(source.getControllerId()); if (player != null) { - player.setCanLoseLife(false); + affectedObjects.add(player); return true; } return false; diff --git a/Mage.Sets/src/mage/cards/c/CrownOfConvergence.java b/Mage.Sets/src/mage/cards/c/CrownOfConvergence.java index 1360af11e59e..86acf5fe9e79 100644 --- a/Mage.Sets/src/mage/cards/c/CrownOfConvergence.java +++ b/Mage.Sets/src/mage/cards/c/CrownOfConvergence.java @@ -1,6 +1,7 @@ package mage.cards.c; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleStaticAbility; @@ -16,13 +17,14 @@ import mage.cards.CardsImpl; import mage.constants.CardType; import mage.constants.Duration; +import mage.constants.Layer; import mage.constants.Outcome; -import mage.constants.Zone; import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import java.util.List; import java.util.UUID; /** @@ -70,21 +72,21 @@ private CrownOfConvergenceColorBoostEffect(CrownOfConvergenceColorBoostEffect ef } @Override - public boolean apply(Game game, Ability source) { - Player you = game.getPlayer(source.getControllerId()); - if (you != null) { - Card topCard = you.getLibrary().getFromTop(game); - if (topCard != null) { - for (Permanent permanent : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_CONTROLLED_CREATURE, source.getControllerId(), source, game)) { - if (permanent.getColor(game).shares(topCard.getColor(game)) && !permanent.getColor(game).isColorless()) { - permanent.addPower(power.calculate(game, source, this)); - permanent.addToughness(toughness.calculate(game, source, this)); - } - } + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return false; + } + Card topCard = controller.getLibrary().getFromTop(game); + if (topCard == null) { + return false; + } + for (Permanent permanent : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, controller.getId(), game)) { + if (permanent.getColor(game).shares(topCard.getColor(game))) { + affectedObjects.add(permanent); } - return true; } - return false; + return !affectedObjects.isEmpty(); } @Override diff --git a/Mage.Sets/src/mage/cards/c/CrownOfEmpires.java b/Mage.Sets/src/mage/cards/c/CrownOfEmpires.java index d7c4e88a5e04..f8f88b7d3819 100644 --- a/Mage.Sets/src/mage/cards/c/CrownOfEmpires.java +++ b/Mage.Sets/src/mage/cards/c/CrownOfEmpires.java @@ -1,7 +1,7 @@ package mage.cards.c; +import mage.MageItem; import mage.abilities.Ability; -import mage.abilities.Mode; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; @@ -17,6 +17,7 @@ import mage.target.targetpointer.FixedTarget; import mage.util.CardUtil; +import java.util.List; import java.util.UUID; /** @@ -102,11 +103,20 @@ public CrownOfEmpiresControlEffect copy() { } @Override - public boolean apply(Game game, Ability source) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + UUID controllerId = (UUID) game.getState().getValue(source.getSourceId().toString()); + for (MageItem object : affectedObjects) { + ((Permanent) object).changeControllerId(controllerId, game, source); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); UUID controllerId = (UUID) game.getState().getValue(source.getSourceId().toString()); if (permanent != null && controllerId != null) { - return permanent.changeControllerId(controllerId, game, source); + affectedObjects.add(permanent); + return true; } return false; } diff --git a/Mage.Sets/src/mage/cards/c/CurseOfConformity.java b/Mage.Sets/src/mage/cards/c/CurseOfConformity.java index 5ef27c7d9f68..34d38fba2126 100644 --- a/Mage.Sets/src/mage/cards/c/CurseOfConformity.java +++ b/Mage.Sets/src/mage/cards/c/CurseOfConformity.java @@ -1,5 +1,6 @@ package mage.cards.c; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousEffectImpl; @@ -15,6 +16,8 @@ import mage.game.permanent.Permanent; import mage.target.TargetPlayer; +import java.util.ArrayList; +import java.util.List; import java.util.UUID; /** @@ -73,10 +76,9 @@ public CurseOfConformityEffect copy() { } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - for (Permanent permanent : game.getBattlefield().getActivePermanents( - filter, source.getControllerId(), source, game - )) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; switch (layer) { case TypeChangingEffects_4: permanent.removeAllCreatureTypes(game); @@ -88,16 +90,26 @@ public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) } } } - return true; } @Override - public boolean hasLayer(Layer layer) { - return layer == Layer.TypeChangingEffects_4 || layer == Layer.PTChangingEffects_7; + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + affectedObjects.addAll(game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game)); + return !affectedObjects.isEmpty(); } @Override - public boolean apply(Game game, Ability source) { + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + List affectedObjects = new ArrayList<>(); + if (queryAffectedObjects(layer, source, game, affectedObjects)) { + applyToObjects(layer, sublayer, source, game, affectedObjects); + return true; + } return false; } + + @Override + public boolean hasLayer(Layer layer) { + return layer == Layer.TypeChangingEffects_4 || layer == Layer.PTChangingEffects_7; + } } diff --git a/Mage.Sets/src/mage/cards/c/CurseclothWrappings.java b/Mage.Sets/src/mage/cards/c/CurseclothWrappings.java index a74c3ed7b363..201f08e6e438 100644 --- a/Mage.Sets/src/mage/cards/c/CurseclothWrappings.java +++ b/Mage.Sets/src/mage/cards/c/CurseclothWrappings.java @@ -1,7 +1,6 @@ package mage.cards.c; -import java.util.UUID; - +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleStaticAbility; @@ -12,17 +11,15 @@ import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Layer; -import mage.constants.Outcome; -import mage.constants.SubLayer; -import mage.constants.SubType; +import mage.constants.*; import mage.filter.common.FilterCreatureCard; import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.target.common.TargetCardInYourGraveyard; +import java.util.List; +import java.util.UUID; + /** * * @author Jmlundeen @@ -77,11 +74,19 @@ public CurseClothWrappingsEffect copy() { } @Override - public boolean apply(Game game, Ability source) { - Card card = game.getCard(getTargetPointer().getFirst(game, source)); - if (card != null) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Card card = (Card) object; EmbalmAbility embalmAbility = new EmbalmAbility(card.getManaCost(), card); game.getState().addOtherAbility(card, embalmAbility); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + Card card = game.getCard(getTargetPointer().getFirst(game, source)); + if (card != null) { + affectedObjects.add(card); return true; } return false; diff --git a/Mage.Sets/src/mage/cards/c/CursedRack.java b/Mage.Sets/src/mage/cards/c/CursedRack.java index 570bf0a48584..6076e900e42b 100644 --- a/Mage.Sets/src/mage/cards/c/CursedRack.java +++ b/Mage.Sets/src/mage/cards/c/CursedRack.java @@ -1,7 +1,7 @@ package mage.cards.c; -import java.util.UUID; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.SimpleStaticAbility; @@ -13,6 +13,9 @@ import mage.game.Game; import mage.players.Player; +import java.util.List; +import java.util.UUID; + /** * * @author MarcoMarin @@ -56,11 +59,19 @@ public CursedRackHandSizeEffect copy() { } @Override - public boolean apply(Game game, Ability source) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + UUID playerId = (UUID) game.getState().getValue(source.getSourceId() + ChooseOpponentEffect.VALUE_KEY); + for (MageItem object : affectedObjects) { + ((Player) object).setMaxHandSize(4); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { UUID playerId = (UUID) game.getState().getValue(source.getSourceId() + ChooseOpponentEffect.VALUE_KEY); Player opponent = game.getPlayer(playerId); if (opponent != null) { - opponent.setMaxHandSize(4); + affectedObjects.add(opponent); return true; } return false; diff --git a/Mage.Sets/src/mage/cards/c/CyberdriveAwakener.java b/Mage.Sets/src/mage/cards/c/CyberdriveAwakener.java index 469c5c7e0813..db8921f8cdca 100644 --- a/Mage.Sets/src/mage/cards/c/CyberdriveAwakener.java +++ b/Mage.Sets/src/mage/cards/c/CyberdriveAwakener.java @@ -1,6 +1,7 @@ package mage.cards.c; import mage.MageInt; +import mage.MageItem; import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; @@ -18,6 +19,7 @@ import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.UUID; @@ -87,19 +89,10 @@ public void init(Ability source, Game game) { .map(permanent -> new MageObjectReference(permanent, game)) .forEach(affectedObjectList::add); } - @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - List permanents = affectedObjectList - .stream() - .map(mor -> mor.getPermanent(game)) - .filter(Objects::nonNull) - .collect(Collectors.toList()); - if (permanents.isEmpty()) { - discard(); - return false; - } - for (Permanent permanent : permanents) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; switch (layer) { case TypeChangingEffects_4: permanent.addCardType(game, CardType.ARTIFACT, CardType.CREATURE); @@ -111,20 +104,39 @@ public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) } } } - return true; } @Override - public boolean hasLayer(Layer layer) { - return layer == Layer.TypeChangingEffects_4 - || layer == Layer.PTChangingEffects_7; + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + List permanents = affectedObjectList + .stream() + .map(mor -> mor.getPermanent(game)) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + if (permanents.isEmpty()) { + discard(); + return false; + } + affectedObjects.addAll(permanents); + return true; } @Override - public boolean apply(Game game, Ability source) { + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + List affectedObjects = new ArrayList<>(); + if (queryAffectedObjects(layer, source, game, affectedObjects)) { + applyToObjects(layer, sublayer, source, game, affectedObjects); + return true; + } return false; } + @Override + public boolean hasLayer(Layer layer) { + return layer == Layer.TypeChangingEffects_4 + || layer == Layer.PTChangingEffects_7; + } + @Override public CyberdriveAwakenerEffect copy() { return new CyberdriveAwakenerEffect(this); diff --git a/Mage.Sets/src/mage/cards/c/CyclopeanTomb.java b/Mage.Sets/src/mage/cards/c/CyclopeanTomb.java index 2de29c123d31..ed13a036276f 100644 --- a/Mage.Sets/src/mage/cards/c/CyclopeanTomb.java +++ b/Mage.Sets/src/mage/cards/c/CyclopeanTomb.java @@ -1,5 +1,6 @@ package mage.cards.c; +import mage.MageItem; import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.DelayedTriggeredAbility; @@ -82,13 +83,13 @@ private BecomeSwampEffect(final BecomeSwampEffect effect) { } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Permanent land = game.getPermanent(this.getTargetPointer().getFirst(game, source)); if (land == null || land.getCounters(game).getCount(CounterType.MIRE) < 1) { this.discard(); return false; } - return super.apply(layer, sublayer, source, game); + return true; } @Override diff --git a/Mage.Sets/src/mage/cards/d/DanLewis.java b/Mage.Sets/src/mage/cards/d/DanLewis.java index cfc362c3377a..17d1046f0053 100644 --- a/Mage.Sets/src/mage/cards/d/DanLewis.java +++ b/Mage.Sets/src/mage/cards/d/DanLewis.java @@ -1,6 +1,7 @@ package mage.cards.d; import mage.MageInt; +import mage.MageItem; import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; @@ -17,6 +18,8 @@ import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.ArrayList; +import java.util.List; import java.util.UUID; /** @@ -68,15 +71,9 @@ private DanLewisEffect(final DanLewisEffect effect) { } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - if (layer == Layer.TypeChangingEffects_4) { - affectedObjectList.clear(); - for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game)) { - affectedObjectList.add(new MageObjectReference(permanent, game)); - } - } - for (MageObjectReference mor : affectedObjectList) { - Permanent permanent = mor.getPermanent(game); + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; switch (layer) { case TypeChangingEffects_4: permanent.addSubType(game, SubType.EQUIPMENT); @@ -88,11 +85,34 @@ public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) permanent.addAbility(new EquipAbility(1, false), source.getSourceId(), game); } } - return true; } @Override - public boolean apply(Game game, Ability source) { + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + if (layer == Layer.TypeChangingEffects_4) { + affectedObjectList.clear(); + for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game)) { + affectedObjectList.add(new MageObjectReference(permanent, game)); + affectedObjects.add(permanent); + } + } else { + for (MageObjectReference mor : affectedObjectList) { + Permanent permanent = mor.getPermanent(game); + if (permanent != null) { + affectedObjects.add(permanent); + } + } + } + return !affectedObjects.isEmpty(); + } + + @Override + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + List affectedObjects = new ArrayList<>(); + if (queryAffectedObjects(layer, source, game, affectedObjects)) { + applyToObjects(layer, sublayer, source, game, affectedObjects); + return true; + } return false; } diff --git a/Mage.Sets/src/mage/cards/d/DarkImpostor.java b/Mage.Sets/src/mage/cards/d/DarkImpostor.java index 34ca02b5c1d0..db0a9505125a 100644 --- a/Mage.Sets/src/mage/cards/d/DarkImpostor.java +++ b/Mage.Sets/src/mage/cards/d/DarkImpostor.java @@ -1,6 +1,7 @@ package mage.cards.d; import mage.MageInt; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleStaticAbility; @@ -21,6 +22,7 @@ import mage.target.common.TargetCreaturePermanent; import mage.util.CardUtil; +import java.util.List; import java.util.UUID; /** @@ -100,19 +102,31 @@ private DarkImpostorContinuousEffect(final DarkImpostorContinuousEffect effect) } @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = source.getSourcePermanentIfItStillExists(game); - ExileZone exileZone = game.getExile().getExileZone(CardUtil.getExileZoneId(game, source)); - if (permanent == null || exileZone == null || exileZone.isEmpty()) { - return false; - } - for (Card card : exileZone.getCards(StaticFilters.FILTER_CARD_CREATURE, game)) { - for (Ability ability : card.getAbilities(game)) { - if (ability.isActivatedAbility()) { - permanent.addAbility(ability, source.getSourceId(), game, true); + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; + ExileZone exileZone = game.getExile().getExileZone(CardUtil.getExileZoneId(game, source, permanent.getZoneChangeCounter(game))); + if (exileZone == null || exileZone.isEmpty()) { + continue; + } + for (Card card : exileZone.getCards(StaticFilters.FILTER_CARD_CREATURE, game)) { + for (Ability ability : card.getAbilities(game)) { + if (ability.isActivatedAbility()) { + permanent.addAbility(ability, source.getSourceId(), game); + } } } } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + Permanent permanent = source.getSourcePermanentIfItStillExists(game); + if (permanent == null) { + return false; + } + affectedObjects.add(permanent); return true; } diff --git a/Mage.Sets/src/mage/cards/d/DarkestHour.java b/Mage.Sets/src/mage/cards/d/DarkestHour.java index 297069926a91..4226d9ef7bdd 100644 --- a/Mage.Sets/src/mage/cards/d/DarkestHour.java +++ b/Mage.Sets/src/mage/cards/d/DarkestHour.java @@ -1,7 +1,7 @@ package mage.cards.d; -import java.util.UUID; +import mage.MageItem; import mage.ObjectColor; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; @@ -13,6 +13,9 @@ import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.List; +import java.util.UUID; + /** * * @author emerald000 @@ -48,11 +51,17 @@ private DarkestHourEffect(final DarkestHourEffect effect) { } @Override - public boolean apply(Game game, Ability source) { - for (Permanent permanent : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), source, game)) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; permanent.getColor(game).setColor(ObjectColor.BLACK); } - return true; + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + affectedObjects.addAll(game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), source, game)); + return !affectedObjects.isEmpty(); } @Override diff --git a/Mage.Sets/src/mage/cards/d/DarksteelMonolith.java b/Mage.Sets/src/mage/cards/d/DarksteelMonolith.java index 158d6a8747b6..bf1a09cf9021 100644 --- a/Mage.Sets/src/mage/cards/d/DarksteelMonolith.java +++ b/Mage.Sets/src/mage/cards/d/DarksteelMonolith.java @@ -1,5 +1,6 @@ package mage.cards.d; +import mage.MageItem; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; @@ -19,6 +20,7 @@ import mage.game.stack.Spell; import mage.players.Player; +import java.util.List; import java.util.UUID; /** @@ -112,7 +114,7 @@ public boolean activateAlternativeCosts(Ability ability, Game game) { class DarksteelMonolithAddAltCostEffect extends ContinuousEffectImpl { DarksteelMonolithAddAltCostEffect() { - super(Duration.WhileOnBattlefield, Outcome.Benefit); + super(Duration.WhileOnBattlefield, Layer.RulesEffects, SubLayer.NA, Outcome.Benefit); staticText = "Once each turn, you may pay {0} rather than pay the mana cost for a colorless spell you cast from your hand."; } @@ -126,35 +128,31 @@ public DarksteelMonolithAddAltCostEffect copy() { } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - Permanent sourcePermanent = game.getPermanent(source.getSourceId()); - if (sourcePermanent != null) { - Boolean wasItUsed = (Boolean) game.getState().getValue( - sourcePermanent.getId().toString() - + sourcePermanent.getZoneChangeCounter(game) - + sourcePermanent.getTurnsOnBattlefield()); - // If we haven't used it yet this turn, give the option of using the zero alternative cost - if (wasItUsed == null) { - DarksteelMonolithAlternativeCost alternateCostAbility = new DarksteelMonolithAlternativeCost(); - alternateCostAbility.setSourceId(source.getSourceId()); - controller.getAlternativeSourceCosts().add(alternateCostAbility); - } - // Return true even if we didn't add the alt cost. We still applied the effect - return true; + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent sourcePermanent = (Permanent) object; + Player controller = game.getPlayer(source.getControllerId()); + Boolean wasItUsed = (Boolean) game.getState().getValue( + sourcePermanent.getId().toString() + + sourcePermanent.getZoneChangeCounter(game) + + sourcePermanent.getTurnsOnBattlefield()); + // If we haven't used it yet this turn, give the option of using the zero alternative cost + if (wasItUsed == null) { + DarksteelMonolithAlternativeCost alternateCostAbility = new DarksteelMonolithAlternativeCost(); + alternateCostAbility.setSourceId(source.getSourceId()); + controller.getAlternativeSourceCosts().add(alternateCostAbility); } } - return false; } @Override - public boolean apply(Game game, Ability source) { - return false; - } - - @Override - public boolean hasLayer(Layer layer) { - return layer == Layer.RulesEffects; + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + Player controller = game.getPlayer(source.getControllerId()); + Permanent permanent = game.getPermanent(source.getSourceId()); + if (controller == null || permanent == null) { + return false; + } + affectedObjects.add(permanent); + return true; } } diff --git a/Mage.Sets/src/mage/cards/d/DeathMaskDuplicant.java b/Mage.Sets/src/mage/cards/d/DeathMaskDuplicant.java index bc7eb7d2280d..327824643efc 100644 --- a/Mage.Sets/src/mage/cards/d/DeathMaskDuplicant.java +++ b/Mage.Sets/src/mage/cards/d/DeathMaskDuplicant.java @@ -1,42 +1,27 @@ package mage.cards.d; -import java.util.UUID; import mage.MageInt; +import mage.MageItem; import mage.abilities.Ability; -import mage.abilities.MageSingleton; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.common.ExileTargetEffect; -import mage.abilities.keyword.DoubleStrikeAbility; -import mage.abilities.keyword.FearAbility; -import mage.abilities.keyword.FirstStrikeAbility; -import mage.abilities.keyword.FlyingAbility; -import mage.abilities.keyword.HasteAbility; -import mage.abilities.keyword.LandwalkAbility; -import mage.abilities.keyword.ProtectionAbility; -import mage.abilities.keyword.TrampleAbility; +import mage.abilities.keyword.*; import mage.cards.Card; -import mage.constants.SubType; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.AbilityWord; -import mage.constants.CardType; -import mage.constants.DependencyType; -import mage.constants.Duration; -import mage.constants.Layer; -import mage.constants.Outcome; -import mage.constants.SubLayer; -import mage.constants.Zone; +import mage.constants.*; import mage.filter.StaticFilters; import mage.game.ExileZone; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.players.Player; import mage.target.common.TargetCardInYourGraveyard; import mage.util.CardUtil; +import java.util.*; + /** * * @author TheElk801 @@ -71,6 +56,17 @@ public DeathMaskDuplicant copy() { static class DeathMaskDuplicantEffect extends ContinuousEffectImpl { + private static final Set> KEYWORD_ABILITIES = new HashSet<>(Arrays.asList( + FlyingAbility.class, + FearAbility.class, + FirstStrikeAbility.class, + DoubleStrikeAbility.class, + HasteAbility.class, + LandwalkAbility.class, + ProtectionAbility.class, + TrampleAbility.class + )); + public DeathMaskDuplicantEffect() { super(Duration.WhileOnBattlefield, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility); this.addDependedToType(DependencyType.AddingAbility); @@ -82,43 +78,46 @@ private DeathMaskDuplicantEffect(final DeathMaskDuplicantEffect effect) { } @Override - public boolean apply(Game game, Ability source) { - Permanent sourceObject = game.getPermanent(source.getSourceId()); + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + Set exileAbilities = new HashSet<>(); + + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; + getAbilitiesInExile(game, source, permanent, exileAbilities); + for (Ability ability : exileAbilities) { + if (isValidKeywordAbility(ability.getClass())) { + permanent.addAbility(ability, source.getSourceId(), game); + } + } + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + Permanent sourcePermanent = game.getPermanent(source.getSourceId()); - if (sourceObject == null) { + if (sourcePermanent == null) { return false; } + affectedObjects.add(sourcePermanent); + return true; + } - for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) { - Player player = game.getPlayer(playerId); - if (player != null) { - ExileZone exileZone = game.getState().getExile().getExileZone(CardUtil.getExileZoneId(game, source.getSourceId(), sourceObject.getZoneChangeCounter(game))); - if (exileZone != null && !exileZone.isEmpty()) { - for (UUID cardId : exileZone) { - Card card = game.getCard(cardId); - if (card != null && card.isCreature(game)) { - for (Ability ability : card.getAbilities(game)) { - if (ability instanceof MageSingleton) { - if (ability instanceof FlyingAbility - || ability instanceof FearAbility - || ability instanceof FirstStrikeAbility - || ability instanceof DoubleStrikeAbility - || ability instanceof HasteAbility - || ability instanceof TrampleAbility) { - sourceObject.addAbility(ability, source.getSourceId(), game); - } - } else if (ability instanceof ProtectionAbility - || ability instanceof LandwalkAbility) { - sourceObject.addAbility(ability, source.getSourceId(), game); - } - } - } - } - } - } + private void getAbilitiesInExile(Game game, Ability source, Permanent sourcePermanent, Set exileAbilities) { + ExileZone exileZone = game.getState().getExile().getExileZone(CardUtil.getExileZoneId(game, source.getSourceId(), sourcePermanent.getZoneChangeCounter(game))); + if (exileZone == null || exileZone.isEmpty()) { + return; } + for (Card card : exileZone.getCards(StaticFilters.FILTER_CARD_CREATURE, game)) { + exileAbilities.addAll(card.getAbilities(game)); + } + } - return true; + private boolean isValidKeywordAbility(Class abilityClass) { + return KEYWORD_ABILITIES.stream() + .anyMatch(keywordClass -> + keywordClass.isAssignableFrom(abilityClass) + ); } @Override diff --git a/Mage.Sets/src/mage/cards/d/DemonOfFatesDesign.java b/Mage.Sets/src/mage/cards/d/DemonOfFatesDesign.java index c58c0001da61..5f09412d987c 100644 --- a/Mage.Sets/src/mage/cards/d/DemonOfFatesDesign.java +++ b/Mage.Sets/src/mage/cards/d/DemonOfFatesDesign.java @@ -1,6 +1,7 @@ package mage.cards.d; import mage.MageInt; +import mage.MageItem; import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; @@ -34,6 +35,7 @@ import mage.watchers.Watcher; import java.util.HashSet; +import java.util.List; import java.util.Set; import java.util.UUID; @@ -191,19 +193,26 @@ public DemonOfFatesDesignCastEffect copy() { } @Override - public boolean apply(Game game, Ability source) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Player controller = (Player) object; + controller.getAlternativeSourceCosts().add(alternativeCastingCostAbility); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Player controller = game.getPlayer(source.getControllerId()); DemonOfFatesDesignWatcher watcher = game.getState().getWatcher(DemonOfFatesDesignWatcher.class); if (controller == null || watcher == null) { return false; } - alternativeCastingCostAbility.setSourceId(source.getSourceId()); if (!watcher.canAbilityBeUsed(game, source, alternativeCastingCostAbility.getMor(game))) { return false; } - controller.getAlternativeSourceCosts().add(alternativeCastingCostAbility); + affectedObjects.add(controller); return true; } } diff --git a/Mage.Sets/src/mage/cards/d/DesdemonaFreedomsEdge.java b/Mage.Sets/src/mage/cards/d/DesdemonaFreedomsEdge.java index f25d9dcec51c..d75e5b533193 100644 --- a/Mage.Sets/src/mage/cards/d/DesdemonaFreedomsEdge.java +++ b/Mage.Sets/src/mage/cards/d/DesdemonaFreedomsEdge.java @@ -1,23 +1,25 @@ package mage.cards.d; -import java.util.UUID; - import mage.MageInt; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.keyword.EscapeAbility; -import mage.cards.Card; -import mage.constants.*; import mage.abilities.keyword.VigilanceAbility; +import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.*; import mage.filter.common.FilterCreatureCard; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.ManaValuePredicate; import mage.game.Game; import mage.target.common.TargetCardInYourGraveyard; +import java.util.List; +import java.util.UUID; + /** * @author Cguy7777 */ @@ -77,15 +79,23 @@ private DesdemonaFreedomsEdgeEffect(final DesdemonaFreedomsEdgeEffect effect) { } @Override - public boolean apply(Game game, Ability source) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Card card = (Card) object; + Ability ability = new EscapeAbility(card, card.getManaCost().getText(), 2); + ability.setSourceId(card.getId()); + ability.setControllerId(card.getOwnerId()); + game.getState().addOtherAbility(card, ability); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Card card = game.getCard(getTargetPointer().getFirst(game, source)); if (card == null || card.getManaCost().getText().isEmpty()) { return false; } - Ability ability = new EscapeAbility(card, card.getManaCost().getText(), 2); - ability.setSourceId(card.getId()); - ability.setControllerId(card.getOwnerId()); - game.getState().addOtherAbility(card, ability); + affectedObjects.add(card); return true; } diff --git a/Mage.Sets/src/mage/cards/d/DireBlunderbuss.java b/Mage.Sets/src/mage/cards/d/DireBlunderbuss.java index 3088dada74ad..781fd3192935 100644 --- a/Mage.Sets/src/mage/cards/d/DireBlunderbuss.java +++ b/Mage.Sets/src/mage/cards/d/DireBlunderbuss.java @@ -1,5 +1,6 @@ package mage.cards.d; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; @@ -24,6 +25,7 @@ import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.FixedTarget; +import java.util.List; import java.util.UUID; /** @@ -86,13 +88,23 @@ public void init(Ability source, Game game) { } @Override - public boolean apply(Game game, Ability source) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; + Ability ability = makeAbility(game, source); + ability.getEffects().setValue("attachedPermanent", game.getPermanent(source.getSourceId())); + permanent.addAbility(ability, source.getSourceId(), game); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Permanent permanent = null; if (getAffectedObjectsSet()) { permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); if (permanent == null) { discard(); - return true; + return false; } } else { Permanent equipment = game.getPermanent(source.getSourceId()); @@ -101,11 +113,9 @@ public boolean apply(Game game, Ability source) { } } if (permanent == null) { - return true; + return false; } - Ability ability = makeAbility(game, source); - ability.getEffects().setValue("attachedPermanent", game.getPermanent(source.getSourceId())); - permanent.addAbility(ability, source.getSourceId(), game); + affectedObjects.add(permanent); return true; } diff --git a/Mage.Sets/src/mage/cards/d/DismissIntoDream.java b/Mage.Sets/src/mage/cards/d/DismissIntoDream.java index c504fd86cd4d..e6f8492870a3 100644 --- a/Mage.Sets/src/mage/cards/d/DismissIntoDream.java +++ b/Mage.Sets/src/mage/cards/d/DismissIntoDream.java @@ -1,7 +1,7 @@ package mage.cards.d; -import java.util.UUID; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.BecomesTargetSourceTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; @@ -15,6 +15,9 @@ import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.List; +import java.util.UUID; + /** * * @author LevelX2 @@ -56,27 +59,24 @@ private DismissIntoDreamEffect(final DismissIntoDreamEffect effect) { super(effect); } - @Override - public boolean apply(Game game, Ability source) { - return false; - } - @Override public DismissIntoDreamEffect copy() { return new DismissIntoDreamEffect(this); } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - super.apply(layer, sublayer, source, game); - - if (layer == Layer.AbilityAddingRemovingEffects_6) { - for (Permanent object: game.getBattlefield().getActivePermanents(this.filter, source.getControllerId(), game)) { - object.addAbility(new BecomesTargetSourceTriggeredAbility(new SacrificeSourceEffect()), source.getSourceId(), game); + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; + switch (layer) { + case TypeChangingEffects_4: + permanent.addSubType(game, this.subType); + break; + case AbilityAddingRemovingEffects_6: + permanent.addAbility(new BecomesTargetSourceTriggeredAbility(new SacrificeSourceEffect()), source.getSourceId(), game); + break; } } - - return true; } @Override diff --git a/Mage.Sets/src/mage/cards/d/DomriChaosBringer.java b/Mage.Sets/src/mage/cards/d/DomriChaosBringer.java index d2e9282b4fcb..b102b4ea3c76 100644 --- a/Mage.Sets/src/mage/cards/d/DomriChaosBringer.java +++ b/Mage.Sets/src/mage/cards/d/DomriChaosBringer.java @@ -1,16 +1,19 @@ package mage.cards.d; +import mage.MageItem; import mage.MageObject; import mage.Mana; import mage.abilities.Ability; import mage.abilities.DelayedTriggeredAbility; import mage.abilities.LoyaltyAbility; +import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.GetEmblemEffect; import mage.abilities.effects.common.LookLibraryAndPickControllerEffect; -import mage.abilities.effects.mana.ManaEffect; import mage.abilities.effects.mana.BasicManaEffect; +import mage.abilities.effects.mana.ManaEffect; import mage.abilities.keyword.RiotAbility; +import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; @@ -18,11 +21,11 @@ import mage.game.Game; import mage.game.command.emblems.DomriChaosBringerEmblem; import mage.game.events.GameEvent; +import mage.game.stack.StackObject; import mage.players.Player; +import java.util.List; import java.util.UUID; -import mage.abilities.effects.ContinuousEffectImpl; -import mage.game.stack.StackObject; /** * @author TheElk801 @@ -167,11 +170,19 @@ public DomriChaosBringAddRiotToSpellEffect copy() { } @Override - public boolean apply(Game game, Ability source) { - if (cardId != null) { - game.getState().addOtherAbility(game.getCard(cardId), riotAbility); - return true; + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + game.getState().addOtherAbility((Card) object, riotAbility); } - return false; + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + Card card = game.getCard(cardId); + if (card == null) { + return false; + } + affectedObjects.add(card); + return true; } } diff --git a/Mage.Sets/src/mage/cards/d/DoorOfDestinies.java b/Mage.Sets/src/mage/cards/d/DoorOfDestinies.java index 22fcd5cfdf09..e6e110ae801c 100644 --- a/Mage.Sets/src/mage/cards/d/DoorOfDestinies.java +++ b/Mage.Sets/src/mage/cards/d/DoorOfDestinies.java @@ -1,31 +1,33 @@ package mage.cards.d; -import java.util.UUID; -import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.common.ChooseCreatureTypeEffect; +import mage.abilities.effects.common.continuous.BoostAllOfChosenSubtypeEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; import mage.counters.CounterType; -import mage.filter.StaticFilters; +import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.game.events.GameEvent; -import mage.game.events.GameEvent.EventType; -import mage.game.permanent.Permanent; import mage.game.stack.Spell; +import java.util.UUID; + /** * * @author Plopman */ public final class DoorOfDestinies extends CardImpl { + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creatures you control of the chosen type"); + static { + filter.add(TargetController.YOU.getControllerPredicate()); + } public DoorOfDestinies(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}"); @@ -36,7 +38,8 @@ public DoorOfDestinies(UUID ownerId, CardSetInfo setInfo) { this.addAbility(new AddCounterAbility()); // Creatures you control of the chosen type get +1/+1 for each charge counter on Door of Destinies. - this.addAbility(new SimpleStaticAbility(new BoostCreatureEffectEffect())); + this.addAbility(new SimpleStaticAbility(new BoostAllOfChosenSubtypeEffect(1, 1, + Duration.WhileOnBattlefield, filter, false))); } private DoorOfDestinies(final DoorOfDestinies card) { @@ -88,39 +91,3 @@ public String getRule() { return "Whenever you cast a spell of the chosen type, put a charge counter on {this}."; } } - -class BoostCreatureEffectEffect extends ContinuousEffectImpl { - - BoostCreatureEffectEffect() { - super(Duration.WhileOnBattlefield, Layer.PTChangingEffects_7, SubLayer.ModifyPT_7c, Outcome.BoostCreature); - staticText = "Creatures you control of the chosen type get +1/+1 for each charge counter on {this}"; - } - - private BoostCreatureEffectEffect(final BoostCreatureEffectEffect effect) { - super(effect); - } - - @Override - public BoostCreatureEffectEffect copy() { - return new BoostCreatureEffectEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent != null) { - SubType subtype = (SubType) game.getState().getValue(permanent.getId() + "_type"); - if (subtype != null) { - for (Permanent perm : game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURES, source.getControllerId(), game)) { - if (perm.hasSubtype(subtype, game)) { - int boost = permanent.getCounters(game).getCount(CounterType.CHARGE); - perm.addPower(boost); - perm.addToughness(boost); - } - } - } - } - return true; - } - -} diff --git a/Mage.Sets/src/mage/cards/d/DragonsoulKnight.java b/Mage.Sets/src/mage/cards/d/DragonsoulKnight.java index 362077e91c71..ca4c4fb602ac 100644 --- a/Mage.Sets/src/mage/cards/d/DragonsoulKnight.java +++ b/Mage.Sets/src/mage/cards/d/DragonsoulKnight.java @@ -2,6 +2,7 @@ package mage.cards.d; import mage.MageInt; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.ManaCostsImpl; @@ -18,6 +19,7 @@ import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.List; import java.util.UUID; /** @@ -59,32 +61,40 @@ private DragonsoulKnight(final DragonsoulKnight card) { public DragonsoulKnight copy() { return new DragonsoulKnight(this); } +} - private static class DragonsoulKnightEffect extends ContinuousEffectImpl { +class DragonsoulKnightEffect extends ContinuousEffectImpl { - private DragonsoulKnightEffect() { - super(Duration.EndOfTurn, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.BecomeCreature); - staticText = "Until end of turn, {this} becomes a Dragon"; - } + public DragonsoulKnightEffect() { + super(Duration.EndOfTurn, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.BecomeCreature); + staticText = "Until end of turn, {this} becomes a Dragon"; + } - private DragonsoulKnightEffect(final DragonsoulKnightEffect effect) { - super(effect); - } + private DragonsoulKnightEffect(final DragonsoulKnightEffect effect) { + super(effect); + } - @Override - public DragonsoulKnightEffect copy() { - return new DragonsoulKnightEffect(this); - } + @Override + public DragonsoulKnightEffect copy() { + return new DragonsoulKnightEffect(this); + } - @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent == null) { - return false; - } + @Override + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; permanent.removeAllCreatureTypes(game); permanent.addSubType(game, SubType.DRAGON); - return true; } } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + Permanent permanent = game.getPermanent(source.getSourceId()); + if (permanent == null) { + return false; + } + affectedObjects.add(permanent); + return true; + } } diff --git a/Mage.Sets/src/mage/cards/d/DralnuLichLord.java b/Mage.Sets/src/mage/cards/d/DralnuLichLord.java index 42daa2c75739..a25fcd32e6d5 100644 --- a/Mage.Sets/src/mage/cards/d/DralnuLichLord.java +++ b/Mage.Sets/src/mage/cards/d/DralnuLichLord.java @@ -1,6 +1,7 @@ package mage.cards.d; import mage.MageInt; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleStaticAbility; @@ -21,6 +22,7 @@ import mage.game.events.GameEvent; import mage.target.common.TargetCardInYourGraveyard; +import java.util.List; import java.util.UUID; /** @@ -115,13 +117,21 @@ public DralnuLichLordFlashbackEffect copy() { } @Override - public boolean apply(Game game, Ability source) { - Card card = game.getCard(getTargetPointer().getFirst(game, source)); - if (card != null) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Card card = (Card) object; FlashbackAbility ability = new FlashbackAbility(card, card.getManaCost()); ability.setSourceId(card.getId()); ability.setControllerId(card.getOwnerId()); game.getState().addOtherAbility(card, ability); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + Card card = game.getCard(getTargetPointer().getFirst(game, source)); + if (card != null) { + affectedObjects.add(card); return true; } return false; diff --git a/Mage.Sets/src/mage/cards/d/DralnusCrusade.java b/Mage.Sets/src/mage/cards/d/DralnusCrusade.java index f4d07d47e29c..5df15e76db42 100755 --- a/Mage.Sets/src/mage/cards/d/DralnusCrusade.java +++ b/Mage.Sets/src/mage/cards/d/DralnusCrusade.java @@ -1,6 +1,7 @@ package mage.cards.d; +import mage.MageItem; import mage.ObjectColor; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; @@ -13,6 +14,8 @@ import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.ArrayList; +import java.util.List; import java.util.UUID; /** @@ -48,8 +51,9 @@ class DralnusCrusadeEffect extends ContinuousEffectImpl { } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - for (Permanent permanent : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE_GOBLINS, source.getControllerId(), source, game)) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; switch (layer) { case TypeChangingEffects_4: permanent.addSubType(game, SubType.ZOMBIE); @@ -59,7 +63,22 @@ public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) break; } } - return true; + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + affectedObjects.addAll(game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE_GOBLINS, source.getControllerId(), source, game)); + return !affectedObjects.isEmpty(); + } + + @Override + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + List affectedObjects = new ArrayList<>(); + if (queryAffectedObjects(layer, source, game, affectedObjects)) { + applyToObjects(layer, sublayer, source, game, affectedObjects); + return true; + } + return false; } private DralnusCrusadeEffect(final DralnusCrusadeEffect effect) { @@ -71,11 +90,6 @@ public DralnusCrusadeEffect copy() { return new DralnusCrusadeEffect(this); } - @Override - public boolean apply(Game game, Ability source) { - return false; - } - @Override public boolean hasLayer(Layer layer) { return layer == Layer.TypeChangingEffects_4 || layer == Layer.ColorChangingEffects_5; diff --git a/Mage.Sets/src/mage/cards/d/DranaAndLinvala.java b/Mage.Sets/src/mage/cards/d/DranaAndLinvala.java index bf8c376bb138..1a5bdbafedf3 100644 --- a/Mage.Sets/src/mage/cards/d/DranaAndLinvala.java +++ b/Mage.Sets/src/mage/cards/d/DranaAndLinvala.java @@ -1,6 +1,7 @@ package mage.cards.d; import mage.MageInt; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.AsThoughEffectImpl; @@ -19,6 +20,7 @@ import mage.util.CardUtil; import java.util.Collection; +import java.util.List; import java.util.Objects; import java.util.UUID; import java.util.stream.Collectors; @@ -105,12 +107,31 @@ private DranaAndLinvalaGainAbilitiesEffect(final DranaAndLinvalaGainAbilitiesEff } @Override - public boolean apply(Game game, Ability source) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + List abilities = getOpponentActivatedAbilities(game, source); + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; + for (Ability ability : abilities) { + Ability addedAbility = permanent.addAbility(ability, source.getSourceId(), game, true); + if (addedAbility != null) { + addedAbility.getEffects().setValue("dranaLinvalaFlag", true); + } + } + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Permanent perm = source.getSourcePermanentIfItStillExists(game); if (perm == null) { return false; } - for (Ability ability : game + affectedObjects.add(perm); + return true; + } + + private List getOpponentActivatedAbilities(Game game, Ability source) { + return game .getBattlefield() .getActivePermanents( StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE, @@ -121,13 +142,7 @@ public boolean apply(Game game, Ability source) { .flatMap(Collection::stream) .filter(Objects::nonNull) .filter(Ability::isActivatedAbility) - .collect(Collectors.toList())) { - Ability addedAbility = perm.addAbility(ability, source.getSourceId(), game, true); - if (addedAbility != null) { - addedAbility.getEffects().setValue("dranaLinvalaFlag", true); - } - } - return true; + .collect(Collectors.toList()); } @Override diff --git a/Mage.Sets/src/mage/cards/d/DranaTheLastBloodchief.java b/Mage.Sets/src/mage/cards/d/DranaTheLastBloodchief.java index cc908e2334cd..0e0812592825 100644 --- a/Mage.Sets/src/mage/cards/d/DranaTheLastBloodchief.java +++ b/Mage.Sets/src/mage/cards/d/DranaTheLastBloodchief.java @@ -1,6 +1,7 @@ package mage.cards.d; import mage.MageInt; +import mage.MageItem; import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; @@ -24,6 +25,7 @@ import mage.target.TargetCard; import mage.target.common.TargetCardInGraveyard; +import java.util.List; import java.util.UUID; /** @@ -120,19 +122,21 @@ private DranaTheLastBloodchiefSubtypeEffect(final DranaTheLastBloodchiefSubtypeE } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - Permanent creature = mor.getPermanent(game); - if (creature != null) { - creature.addSubType(game, SubType.VAMPIRE); - return true; - } else { - this.used = true; + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; + permanent.addSubType(game, SubType.VAMPIRE); } - return false; } @Override - public boolean apply(Game game, Ability source) { + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + Permanent creature = mor.getPermanent(game); + if (creature != null) { + affectedObjects.add(creature); + return true; + } + this.used = true; return false; } diff --git a/Mage.Sets/src/mage/cards/d/DreamDevourer.java b/Mage.Sets/src/mage/cards/d/DreamDevourer.java index 0ed63bc1e301..6aef2b57fb20 100644 --- a/Mage.Sets/src/mage/cards/d/DreamDevourer.java +++ b/Mage.Sets/src/mage/cards/d/DreamDevourer.java @@ -1,7 +1,7 @@ package mage.cards.d; -import java.util.UUID; import mage.MageInt; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.ForetellSourceControllerTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; @@ -9,13 +9,7 @@ import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.keyword.ForetellAbility; import mage.cards.*; -import mage.constants.SubType; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Layer; -import mage.constants.Outcome; -import mage.constants.SubLayer; -import mage.constants.Zone; +import mage.constants.*; import mage.filter.common.FilterNonlandCard; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.AbilityPredicate; @@ -23,6 +17,9 @@ import mage.players.Player; import mage.util.CardUtil; +import java.util.List; +import java.util.UUID; + /** * * @author jeffwadsworth @@ -78,12 +75,9 @@ public DreamDevourerAddAbilityEffect copy() { } @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller == null) { - return false; - } - for (Card card : controller.getHand().getCards(filter, game)) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Card card = (Card) object; ForetellAbility foretellAbility = null; if (card instanceof SplitCard) { String leftHalfCost = CardUtil.reduceCost(((SplitCard) card).getLeftHalfCard().getManaCost(), 2).getText(); @@ -117,6 +111,15 @@ public boolean apply(Game game, Ability source) { game.getState().addOtherAbility(card, foretellAbility); } } - return true; + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return false; + } + affectedObjects.addAll(controller.getHand().getCards(filter, game)); + return !affectedObjects.isEmpty(); } } diff --git a/Mage.Sets/src/mage/cards/d/DreamHalls.java b/Mage.Sets/src/mage/cards/d/DreamHalls.java index 94b9a4783fb1..d7b7f0cc1612 100644 --- a/Mage.Sets/src/mage/cards/d/DreamHalls.java +++ b/Mage.Sets/src/mage/cards/d/DreamHalls.java @@ -1,7 +1,7 @@ package mage.cards.d; -import java.util.UUID; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.SourceIsSpellCondition; @@ -17,6 +17,9 @@ import mage.game.Game; import mage.players.Player; +import java.util.List; +import java.util.UUID; + /** * * @author LevelX2 @@ -52,7 +55,7 @@ class DreamHallsEffect extends ContinuousEffectImpl { private final AlternativeCostSourceAbility alternativeCastingCostAbility = new AlternativeCostSourceAbility(new DiscardCardCost(filter), SourceIsSpellCondition.instance); public DreamHallsEffect() { - super(Duration.WhileOnBattlefield, Outcome.Detriment); + super(Duration.WhileOnBattlefield, Layer.RulesEffects, SubLayer.NA, Outcome.Detriment); staticText = "Rather than pay the mana cost for a spell, its controller may discard a card that shares a color with that spell"; } @@ -70,30 +73,27 @@ public void init(Ability source, Game game, UUID activePlayerId) { super.init(source, game, activePlayerId); alternativeCastingCostAbility.setSourceId(source.getSourceId()); } - - @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { - Player player = game.getPlayer(playerId); - if (player != null) { - player.getAlternativeSourceCosts().add(alternativeCastingCostAbility); - } - } - - return true; - } - return false; - } @Override - public boolean apply(Game game, Ability source) { - return false; + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Player player = (Player) object; + player.getAlternativeSourceCosts().add(alternativeCastingCostAbility); + } } @Override - public boolean hasLayer(Layer layer) { - return layer == Layer.RulesEffects; + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return false; + } + for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { + Player player = game.getPlayer(playerId); + if (player != null) { + affectedObjects.add(player); + } + } + return true; } } diff --git a/Mage.Sets/src/mage/cards/d/DregscapeSliver.java b/Mage.Sets/src/mage/cards/d/DregscapeSliver.java index bcb5fba0a7ad..9920d4d1c82c 100644 --- a/Mage.Sets/src/mage/cards/d/DregscapeSliver.java +++ b/Mage.Sets/src/mage/cards/d/DregscapeSliver.java @@ -1,6 +1,7 @@ package mage.cards.d; import mage.MageInt; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.mana.ManaCostsImpl; @@ -13,6 +14,7 @@ import mage.game.Game; import mage.players.Player; +import java.util.List; import java.util.UUID; /** @@ -55,7 +57,18 @@ private DregscapeSliverEffect(final DregscapeSliverEffect effect) { } @Override - public boolean apply(Game game, Ability source) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Card card = (Card) object; + UnearthAbility ability = new UnearthAbility(new ManaCostsImpl<>("{2}")); + ability.setSourceId(card.getId()); + ability.setControllerId(card.getOwnerId()); + game.getState().addOtherAbility(card, ability); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Player controller = game.getPlayer(source.getControllerId()); if (controller == null) { return false; @@ -65,16 +78,13 @@ public boolean apply(Game game, Ability source) { if (card == null || !card.isCreature(game) || !card.hasSubtype(SubType.SLIVER, game)) { continue; } - UnearthAbility ability = new UnearthAbility(new ManaCostsImpl<>("{2}")); - ability.setSourceId(cardId); - ability.setControllerId(card.getOwnerId()); - game.getState().addOtherAbility(card, ability); + affectedObjects.add(card); } - return true; + return !affectedObjects.isEmpty(); } @Override public DregscapeSliverEffect copy() { return new DregscapeSliverEffect(this); } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/d/DuneChanter.java b/Mage.Sets/src/mage/cards/d/DuneChanter.java index 23a1c23af933..57777b038636 100644 --- a/Mage.Sets/src/mage/cards/d/DuneChanter.java +++ b/Mage.Sets/src/mage/cards/d/DuneChanter.java @@ -1,6 +1,8 @@ package mage.cards.d; import mage.MageInt; +import mage.MageItem; +import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleStaticAbility; @@ -19,7 +21,6 @@ import mage.filter.StaticFilters; import mage.filter.common.FilterOwnedCard; import mage.game.Game; -import mage.game.permanent.Permanent; import mage.players.Player; import java.util.List; @@ -88,50 +89,52 @@ public DuneChanterContinuousEffect copy() { } @Override - public boolean apply(Game game, Ability source) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + ((MageObject) object).addSubType(game, subType); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { UUID controllerId = source.getControllerId(); Player controller = game.getPlayer(controllerId); if (controller == null) { return false; } - // lands cards you own that aren't on the battlefield // in graveyard for (UUID cardId : controller.getGraveyard()) { Card card = game.getCard(cardId); if (filterCard.match(card, controllerId, source, game) && !card.hasSubtype(subType, game)) { - game.getState().getCreateMageObjectAttribute(card, game).getSubtype().add(subType); + affectedObjects.add(card); } } // on hand for (UUID cardId : controller.getHand()) { Card card = game.getCard(cardId); if (filterCard.match(card, controllerId, source, game) && !card.hasSubtype(subType, game)) { - game.getState().getCreateMageObjectAttribute(card, game).getSubtype().add(subType); + affectedObjects.add(card); } } // in exile for (Card card : game.getState().getExile().getAllCards(game, controllerId)) { if (filterCard.match(card, controllerId, source, game) && !card.hasSubtype(subType, game)) { - game.getState().getCreateMageObjectAttribute(card, game).getSubtype().add(subType); + affectedObjects.add(card); } } // in library for (Card card : controller.getLibrary().getCards(game)) { if (filterCard.match(card, controllerId, source, game) && !card.hasSubtype(subType, game)) { - game.getState().getCreateMageObjectAttribute(card, game).getSubtype().add(subType); + affectedObjects.add(card); } } // lands you control - List lands = game.getBattlefield().getAllActivePermanents( - filterPermanent, controllerId, game); - for (Permanent land : lands) { - if (land != null) { - land.addSubType(game, subType); - } - } - return true; + affectedObjects.addAll(game.getBattlefield().getAllActivePermanents( + filterPermanent, controllerId, game + )); + return !affectedObjects.isEmpty(); } } diff --git a/Mage.Sets/src/mage/cards/d/Duplicant.java b/Mage.Sets/src/mage/cards/d/Duplicant.java index 560300b7464d..79f4b9483aae 100644 --- a/Mage.Sets/src/mage/cards/d/Duplicant.java +++ b/Mage.Sets/src/mage/cards/d/Duplicant.java @@ -1,6 +1,7 @@ package mage.cards.d; import mage.MageInt; +import mage.MageItem; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.Mode; @@ -19,6 +20,7 @@ import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import java.util.ArrayList; import java.util.List; import java.util.UUID; @@ -108,7 +110,27 @@ public DuplicantContinuousEffect copy() { } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; + List imprinted = permanent.getImprinted(); + Card card = game.getCard(imprinted.get(imprinted.size() - 1)); + switch (layer) { + case TypeChangingEffects_4: + permanent.copySubTypesFrom(game, card, SubTypeSet.CreatureType); + break; + case PTChangingEffects_7: + if (sublayer == SubLayer.SetPT_7b) { + permanent.getPower().setModifiedBaseValue(card.getPower().getValue()); + permanent.getToughness().setModifiedBaseValue(card.getToughness().getValue()); + } + break; + } + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Permanent permanent = game.getPermanent(source.getSourceId()); if (permanent == null) { return false; @@ -124,22 +146,17 @@ public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) if (card == null || !card.isCreature(game)) { return false; } - switch (layer) { - case TypeChangingEffects_4: - permanent.copySubTypesFrom(game, card, SubTypeSet.CreatureType); - break; - case PTChangingEffects_7: - if (sublayer == SubLayer.SetPT_7b) { - permanent.getPower().setModifiedBaseValue(card.getPower().getValue()); - permanent.getToughness().setModifiedBaseValue(card.getToughness().getValue()); - } - } + affectedObjects.add(permanent); return true; - } @Override - public boolean apply(Game game, Ability source) { + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + List affectedObjects = new ArrayList<>(); + if (queryAffectedObjects(layer, source, game, affectedObjects)) { + applyToObjects(layer, sublayer, source, game, affectedObjects); + return true; + } return false; } diff --git a/Mage.Sets/src/mage/cards/d/DuskmournsDomination.java b/Mage.Sets/src/mage/cards/d/DuskmournsDomination.java index 02d421b0a3c6..e480c4e3ee13 100644 --- a/Mage.Sets/src/mage/cards/d/DuskmournsDomination.java +++ b/Mage.Sets/src/mage/cards/d/DuskmournsDomination.java @@ -1,5 +1,6 @@ package mage.cards.d; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousEffectImpl; @@ -15,6 +16,7 @@ import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import java.util.List; import java.util.Optional; import java.util.UUID; @@ -70,11 +72,19 @@ public DuskmournsDominationEffect copy() { } @Override - public boolean apply(Game game, Ability source) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; + permanent.removeAllAbilities(source.getSourceId(), game); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Optional.ofNullable(source.getSourcePermanentIfItStillExists(game)) .map(Permanent::getAttachedTo) .map(game::getPermanent) - .ifPresent(permanent -> permanent.removeAllAbilities(source.getSourceId(), game)); - return true; + .ifPresent(affectedObjects::add); + return !affectedObjects.isEmpty(); } } diff --git a/Mage.Sets/src/mage/cards/e/ElugeTheShorelessSea.java b/Mage.Sets/src/mage/cards/e/ElugeTheShorelessSea.java index 49005367aa29..5142ceb6d078 100644 --- a/Mage.Sets/src/mage/cards/e/ElugeTheShorelessSea.java +++ b/Mage.Sets/src/mage/cards/e/ElugeTheShorelessSea.java @@ -1,9 +1,11 @@ package mage.cards.e; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.UUID; import mage.MageInt; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldOrAttacksSourceTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; @@ -131,13 +133,14 @@ public ElugeTheShorelessSeaEffect copy() { } @Override - public boolean apply(Game game, Ability source) { + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Permanent land = game.getPermanent(this.getTargetPointer().getFirst(game, source)); if (land == null || land.getCounters(game).getCount(CounterType.FLOOD) < 1) { discard(); return false; } - return super.apply(game, source); + affectedObjects.add(land); + return true; } } diff --git a/Mage.Sets/src/mage/cards/e/EverythingamajigC.java b/Mage.Sets/src/mage/cards/e/EverythingamajigC.java index b6034e21773c..47531ecd7b5e 100644 --- a/Mage.Sets/src/mage/cards/e/EverythingamajigC.java +++ b/Mage.Sets/src/mage/cards/e/EverythingamajigC.java @@ -9,19 +9,19 @@ import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.costs.mana.VariableManaCost; -import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.common.continuous.BecomesXXConstructSourceEffect; import mage.abilities.effects.common.discard.DiscardTargetEffect; import mage.abilities.effects.mana.ManaEffect; import mage.abilities.hint.common.MyTurnHint; import mage.abilities.mana.ActivatedManaAbilityImpl; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Zone; import mage.game.Game; -import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.TargetPlayer; -import mage.util.CardUtil; import java.util.ArrayList; import java.util.List; @@ -50,7 +50,7 @@ public EverythingamajigC(UUID ownerId, CardSetInfo setInfo) { // Chimeric Staff // X: Everythingamajig becomes an X/X Construct artifact creature until end of turn. - this.addAbility(new SimpleActivatedAbility(new ChimericStaffEffect(), new VariableManaCost(VariableCostType.NORMAL))); + this.addAbility(new SimpleActivatedAbility(new BecomesXXConstructSourceEffect(Duration.EndOfTurn), new VariableManaCost(VariableCostType.NORMAL))); } private EverythingamajigC(final EverythingamajigC card) { @@ -125,58 +125,3 @@ public Mana produceMana(Game game, Ability source) { return new Mana(); } } - -class ChimericStaffEffect extends ContinuousEffectImpl { - - ChimericStaffEffect() { - super(Duration.EndOfTurn, Outcome.BecomeCreature); - staticText = "{this} becomes an X/X Construct artifact creature until end of turn"; - this.dependencyTypes.add(DependencyType.BecomeCreature); - } - - private ChimericStaffEffect(final ChimericStaffEffect effect) { - super(effect); - } - - @Override - public ChimericStaffEffect copy() { - return new ChimericStaffEffect(this); - } - - @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent == null) { - return false; - } - switch (layer) { - case TypeChangingEffects_4: - if (!permanent.isArtifact(game)) { - permanent.addCardType(game, CardType.ARTIFACT); - } - if (!permanent.isCreature(game)) { - permanent.addCardType(game, CardType.CREATURE); - } - permanent.removeAllCreatureTypes(game); - permanent.addSubType(game, SubType.CONSTRUCT); - break; - case PTChangingEffects_7: - if (sublayer == SubLayer.SetPT_7b) { - int xValue = CardUtil.getSourceCostsTag(game, source, "X", 0); - permanent.getPower().setModifiedBaseValue(xValue); - permanent.getToughness().setModifiedBaseValue(xValue); - } - } - 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; - } -} diff --git a/Mage.Sets/src/mage/cards/i/IndigoFaerie.java b/Mage.Sets/src/mage/cards/i/IndigoFaerie.java index 0392935cd8e8..24742b62316b 100644 --- a/Mage.Sets/src/mage/cards/i/IndigoFaerie.java +++ b/Mage.Sets/src/mage/cards/i/IndigoFaerie.java @@ -1,26 +1,22 @@ package mage.cards.i; -import java.util.UUID; import mage.MageInt; +import mage.ObjectColor; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.common.continuous.BecomesColorTargetEffect; 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.Layer; -import mage.constants.Outcome; -import mage.constants.SubLayer; -import mage.constants.Zone; -import mage.game.Game; -import mage.game.permanent.Permanent; +import mage.constants.SubType; import mage.target.TargetPermanent; +import java.util.UUID; + /** * * @author jeffwadsworth @@ -39,7 +35,9 @@ public IndigoFaerie(UUID ownerId, CardSetInfo setInfo) { this.addAbility(FlyingAbility.getInstance()); // {U}: Target permanent becomes blue in addition to its other colors until end of turn. - Ability ability = new SimpleActivatedAbility(new BecomesBlueTargetEffect(), new ManaCostsImpl<>("{U}")); + Ability ability = new SimpleActivatedAbility( + new BecomesColorTargetEffect(ObjectColor.BLUE, true, Duration.EndOfTurn), + new ManaCostsImpl<>("{U}")); ability.addTarget(new TargetPermanent()); this.addAbility(ability); @@ -54,31 +52,3 @@ public IndigoFaerie copy() { return new IndigoFaerie(this); } } - -class BecomesBlueTargetEffect extends ContinuousEffectImpl { - - BecomesBlueTargetEffect() { - super(Duration.EndOfTurn, Layer.ColorChangingEffects_5, SubLayer.NA, Outcome.Neutral); - staticText = "Target permanent becomes blue in addition to its other colors until end of turn"; - } - - private BecomesBlueTargetEffect(final BecomesBlueTargetEffect effect) { - super(effect); - } - - @Override - public BecomesBlueTargetEffect copy() { - return new BecomesBlueTargetEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(source.getFirstTarget()); - if (permanent != null) { - permanent.getColor(game).setBlue(true); - return true; - } - return false; - } - -} diff --git a/Mage.Sets/src/mage/cards/k/KondasBanner.java b/Mage.Sets/src/mage/cards/k/KondasBanner.java index e706ee087a06..ac60cf0bfe33 100644 --- a/Mage.Sets/src/mage/cards/k/KondasBanner.java +++ b/Mage.Sets/src/mage/cards/k/KondasBanner.java @@ -1,5 +1,6 @@ package mage.cards.k; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.AttachableToRestrictedAbility; import mage.abilities.common.SimpleStaticAbility; @@ -11,6 +12,7 @@ import mage.constants.Duration; import mage.constants.SubType; import mage.constants.SuperType; +import mage.constants.Layer; import mage.filter.FilterPermanent; import mage.filter.StaticFilters; import mage.filter.common.FilterCreaturePermanent; @@ -18,6 +20,7 @@ import mage.game.permanent.Permanent; import mage.target.TargetPermanent; +import java.util.List; import java.util.UUID; /** @@ -73,23 +76,20 @@ private KondasBannerTypeBoostEffect(final KondasBannerTypeBoostEffect effect) { } @Override - public boolean apply(Game game, Ability source) { - // Check if the equipment is attached + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Permanent equipment = game.getPermanent(source.getSourceId()); - if (equipment != null && equipment.getAttachedTo() != null) { - Permanent equipedCreature = game.getPermanent(equipment.getAttachedTo()); - if (equipedCreature != null) { - for (Permanent perm : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game)) { - if (perm.shareCreatureTypes(game, equipedCreature)) { - perm.addPower(power.calculate(game, source, this)); - perm.addToughness(toughness.calculate(game, source, this)); - - } + if (equipment == null || equipment.getAttachedTo() == null) { + return false; + } + Permanent equippedCreature = game.getPermanent(equipment.getAttachedTo()); + if (equippedCreature != null) { + for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game)) { + if (permanent.shareCreatureTypes(game, equippedCreature)) { + affectedObjects.add(permanent); } - return true; } } - return false; + return !affectedObjects.isEmpty(); } @Override @@ -113,23 +113,20 @@ private KondasBannerColorBoostEffect(final KondasBannerColorBoostEffect effect) } @Override - public boolean apply(Game game, Ability source) { - // Check if the equipment is attached + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Permanent equipment = game.getPermanent(source.getSourceId()); - if (equipment != null && equipment.getAttachedTo() != null) { - Permanent equipedCreature = game.getPermanent(equipment.getAttachedTo()); - if (equipedCreature != null) { - for (Permanent perm : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game)) { - if (equipedCreature.getColor(game).shares(perm.getColor(game))) { - perm.addPower(power.calculate(game, source, this)); - perm.addToughness(toughness.calculate(game, source, this)); - - } + if (equipment == null || equipment.getAttachedTo() == null) { + return false; + } + Permanent equippedCreature = game.getPermanent(equipment.getAttachedTo()); + if (equippedCreature != null) { + for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game)) { + if (permanent.getColor(game).shares(equippedCreature.getColor(game))) { + affectedObjects.add(permanent); } - return true; } } - return false; + return !affectedObjects.isEmpty(); } @Override diff --git a/Mage.Sets/src/mage/cards/l/LithoformBlight.java b/Mage.Sets/src/mage/cards/l/LithoformBlight.java index a515b49989be..09f4ed6d8555 100644 --- a/Mage.Sets/src/mage/cards/l/LithoformBlight.java +++ b/Mage.Sets/src/mage/cards/l/LithoformBlight.java @@ -1,6 +1,6 @@ package mage.cards.l; -import java.util.UUID; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; @@ -19,6 +19,10 @@ import mage.target.TargetPermanent; import mage.target.common.TargetLandPermanent; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + /** * @author TheElk801 */ @@ -71,32 +75,45 @@ public ChangeLandAttachedEffect copy() { } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; + switch (layer) { + case TypeChangingEffects_4: + permanent.removeAllSubTypes(game, SubTypeSet.NonBasicLandType); + break; + case AbilityAddingRemovingEffects_6: + permanent.removeAllAbilities(source.getSourceId(), game); + permanent.addAbility(new ColorlessManaAbility(), source.getSourceId(), game); + Ability ability = new AnyColorManaAbility(); + ability.addCost(new PayLifeCost(1)); + permanent.addAbility(ability, source.getSourceId(), game); + break; + } + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Permanent enchantment = game.getPermanent(source.getSourceId()); - if (enchantment == null) { + if (enchantment == null || enchantment.getAttachedTo() == null) { return false; } Permanent permanent = game.getPermanent(enchantment.getAttachedTo()); if (permanent == null) { - return true; - } - switch (layer) { - case TypeChangingEffects_4: - permanent.removeAllSubTypes(game, SubTypeSet.NonBasicLandType); - break; - case AbilityAddingRemovingEffects_6: - permanent.removeAllAbilities(source.getSourceId(), game); - permanent.addAbility(new ColorlessManaAbility(), source.getSourceId(), game); - Ability ability = new AnyColorManaAbility(); - ability.addCost(new PayLifeCost(1)); - permanent.addAbility(ability, source.getSourceId(), game); - break; + return false; } + affectedObjects.add(permanent); return true; } @Override - public boolean apply(Game game, Ability source) { + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + List affectedObjects = new ArrayList<>(); + if (queryAffectedObjects(layer, source, game, affectedObjects)) { + applyToObjects(layer, sublayer, source, game, affectedObjects); + return true; + } return false; } diff --git a/Mage.Sets/src/mage/cards/m/MinasMorgulDarkFortress.java b/Mage.Sets/src/mage/cards/m/MinasMorgulDarkFortress.java index 406fbb0d0fe8..ff199d91893d 100644 --- a/Mage.Sets/src/mage/cards/m/MinasMorgulDarkFortress.java +++ b/Mage.Sets/src/mage/cards/m/MinasMorgulDarkFortress.java @@ -1,5 +1,6 @@ package mage.cards.m; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTappedAbility; import mage.abilities.common.SimpleActivatedAbility; @@ -10,15 +11,13 @@ import mage.abilities.mana.BlackManaAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.SubType; -import mage.constants.SuperType; +import mage.constants.*; import mage.counters.CounterType; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.common.TargetCreaturePermanent; +import java.util.List; import java.util.UUID; /** @@ -73,12 +72,17 @@ public MinasMorgulEffect copy() { } @Override - public boolean apply(Game game, Ability source) { - Permanent creature = game.getPermanent(this.getTargetPointer().getFirst(game, source)); - if (creature == null || creature.getCounters(game).getCount(CounterType.SHADOW) < 1) { - discard(); + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + for (UUID targetId : getTargetPointer().getTargets(game, source)) { + Permanent target = game.getPermanent(targetId); + if (target != null && target.getCounters(game).getCount(CounterType.SHADOW) > 0) { + affectedObjects.add(target); + } + } + if (affectedObjects.isEmpty()) { + this.discard(); return false; } - return super.apply(game, source); + return true; } } diff --git a/Mage.Sets/src/mage/cards/n/NewBlood.java b/Mage.Sets/src/mage/cards/n/NewBlood.java index eee9524c5251..243100b77a8a 100644 --- a/Mage.Sets/src/mage/cards/n/NewBlood.java +++ b/Mage.Sets/src/mage/cards/n/NewBlood.java @@ -1,8 +1,8 @@ package mage.cards.n; +import mage.MageItem; import mage.MageObject; import mage.abilities.Ability; -import mage.abilities.Mode; import mage.abilities.costs.common.TapTargetCost; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.ContinuousEffectImpl; @@ -22,6 +22,7 @@ import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.FixedTarget; +import java.util.List; import java.util.UUID; /** @@ -129,11 +130,22 @@ public void init(Ability source, Game game) { } } } + @Override + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + MageObject mageObject = (MageObject) object; + mageObject.removeSubType(game, fromSubType); + mageObject.addSubType(game, toSubType); + } + } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Player controller = game.getPlayer(source.getControllerId()); if (controller == null) { + if (duration == Duration.Custom) { + discard(); + } return false; } if (fromSubType == null) { @@ -145,29 +157,16 @@ public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) if (targetObject != null) { objectFound = true; if (targetObject.hasSubtype(fromSubType, game)) { - targetObject.removeSubType(game, fromSubType); - if (!targetObject.hasSubtype(toSubType, game)) { - targetObject.addSubType(game, toSubType); - } + affectedObjects.add(targetObject); } } - if (!objectFound && this.getDuration() == Duration.Custom) { - this.discard(); - } + } + if (!objectFound && this.getDuration() == Duration.Custom) { + this.discard(); } return true; } - @Override - public boolean apply(Game game, Ability source) { - return false; - } - - @Override - public boolean hasLayer(Layer layer) { - return layer == Layer.TypeChangingEffects_4; - } - @Override public ChangeCreatureTypeTargetEffect copy() { return new ChangeCreatureTypeTargetEffect(this); diff --git a/Mage.Sets/src/mage/cards/n/NightDay.java b/Mage.Sets/src/mage/cards/n/NightDay.java index 9668b2fb0d2b..f8430ca032fe 100644 --- a/Mage.Sets/src/mage/cards/n/NightDay.java +++ b/Mage.Sets/src/mage/cards/n/NightDay.java @@ -1,21 +1,18 @@ package mage.cards.n; -import mage.MageObjectReference; -import mage.abilities.Ability; -import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.common.continuous.BoostAllEffect; import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.cards.CardSetInfo; import mage.cards.SplitCard; -import mage.constants.*; -import mage.filter.StaticFilters; -import mage.game.Game; -import mage.game.permanent.Permanent; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SpellAbilityType; +import mage.constants.TargetController; +import mage.filter.common.FilterCreaturePermanent; import mage.target.TargetPlayer; import mage.target.common.TargetCreaturePermanent; -import java.util.Iterator; -import java.util.List; import java.util.UUID; /** @@ -23,6 +20,12 @@ */ public final class NightDay extends SplitCard { + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Creatures target player controls"); + + static { + filter.add(TargetController.SOURCE_TARGETS.getControllerPredicate()); + } + public NightDay(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{B}", "{2}{W}", SpellAbilityType.SPLIT); @@ -34,7 +37,7 @@ public NightDay(UUID ownerId, CardSetInfo setInfo) { // Day // Creatures target player controls get +1/+1 until end of turn. getRightHalfCard().getSpellAbility().addTarget(new TargetPlayer()); - getRightHalfCard().getSpellAbility().addEffect(new DayEffect()); + getRightHalfCard().getSpellAbility().addEffect(new BoostAllEffect(1, 1, Duration.EndOfTurn, filter, false)); } @@ -47,45 +50,3 @@ public NightDay copy() { return new NightDay(this); } } - -class DayEffect extends ContinuousEffectImpl { - - DayEffect() { - super(Duration.EndOfTurn, Layer.PTChangingEffects_7, SubLayer.ModifyPT_7c, Outcome.BoostCreature); - staticText = "Creatures target player controls get +1/+1 until end of turn"; - } - - private DayEffect(final DayEffect effect) { - super(effect); - } - - @Override - public DayEffect copy() { - return new DayEffect(this); - } - - @Override - public void init(Ability source, Game game) { - super.init(source, game); - if (getAffectedObjectsSet()) { - List creatures = game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, source.getFirstTarget(), game); - for (Permanent creature : creatures) { - affectedObjectList.add(new MageObjectReference(creature, game)); - } - } - } - - @Override - public boolean apply(Game game, Ability source) { - for (Iterator it = affectedObjectList.iterator(); it.hasNext(); ) { - Permanent permanent = it.next().getPermanent(game); - if (permanent != null) { - permanent.addPower(1); - permanent.addToughness(1); - } else { - it.remove(); - } - } - return true; - } -} diff --git a/Mage.Sets/src/mage/cards/s/Scrapbasket.java b/Mage.Sets/src/mage/cards/s/Scrapbasket.java index e13663aad2f5..7f4f3fc58ee7 100644 --- a/Mage.Sets/src/mage/cards/s/Scrapbasket.java +++ b/Mage.Sets/src/mage/cards/s/Scrapbasket.java @@ -1,23 +1,18 @@ package mage.cards.s; -import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; +import mage.ObjectColor; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.common.continuous.BecomesColorSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Duration; -import mage.constants.Layer; -import mage.constants.Outcome; -import mage.constants.SubLayer; -import mage.constants.Zone; -import mage.game.Game; -import mage.game.permanent.Permanent; +import mage.constants.SubType; + +import java.util.UUID; /** * @@ -32,7 +27,7 @@ public Scrapbasket(UUID ownerId, CardSetInfo setInfo) { this.toughness = new MageInt(2); // {1}: Scrapbasket becomes all colors until end of turn. - this.addAbility(new SimpleActivatedAbility(new BecomesAllColorsEffect(), new ManaCostsImpl<>("{1}"))); + this.addAbility(new SimpleActivatedAbility(new BecomesColorSourceEffect(new ObjectColor("WUBRG"), Duration.EndOfTurn), new ManaCostsImpl<>("{1}"))); } @@ -45,35 +40,3 @@ public Scrapbasket copy() { return new Scrapbasket(this); } } - -class BecomesAllColorsEffect extends ContinuousEffectImpl { - - BecomesAllColorsEffect() { - super(Duration.EndOfTurn, Layer.ColorChangingEffects_5, SubLayer.NA, Outcome.Neutral); - staticText = "{this} becomes all colors until end of turn"; - } - - private BecomesAllColorsEffect(final BecomesAllColorsEffect effect) { - super(effect); - } - - @Override - public BecomesAllColorsEffect copy() { - return new BecomesAllColorsEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent != null) { - permanent.getColor(game).setBlack(true); - permanent.getColor(game).setBlue(true); - permanent.getColor(game).setRed(true); - permanent.getColor(game).setGreen(true); - permanent.getColor(game).setWhite(true); - return true; - } - return false; - } - -} diff --git a/Mage.Sets/src/mage/cards/s/SkilledAnimator.java b/Mage.Sets/src/mage/cards/s/SkilledAnimator.java index ada374dc2659..11bc55581ea1 100644 --- a/Mage.Sets/src/mage/cards/s/SkilledAnimator.java +++ b/Mage.Sets/src/mage/cards/s/SkilledAnimator.java @@ -1,7 +1,9 @@ package mage.cards.s; +import java.util.List; import java.util.UUID; import mage.MageInt; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.Mode; import mage.abilities.common.EntersBattlefieldTriggeredAbility; @@ -72,13 +74,12 @@ public SkilledAnimatorBecomesCreatureEffect copy() { } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - Permanent sourcePermanent = game.getPermanent(source.getSourceId()); - if (sourcePermanent == null) { + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + if (game.getPermanent(source.getSourceId()) == null) { this.discard(); return false; } - return super.apply(layer, sublayer, source, game); + return super.queryAffectedObjects(layer, source, game, affectedObjects); } } diff --git a/Mage.Sets/src/mage/cards/s/SongOfTheDryads.java b/Mage.Sets/src/mage/cards/s/SongOfTheDryads.java index d34577f660f9..d507c28e689f 100644 --- a/Mage.Sets/src/mage/cards/s/SongOfTheDryads.java +++ b/Mage.Sets/src/mage/cards/s/SongOfTheDryads.java @@ -1,5 +1,7 @@ package mage.cards.s; +import mage.MageItem; +import mage.ObjectColor; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousEffectImpl; @@ -13,6 +15,8 @@ import mage.game.permanent.Permanent; import mage.target.TargetPermanent; +import java.util.ArrayList; +import java.util.List; import java.util.UUID; /** @@ -58,17 +62,32 @@ private BecomesColorlessForestLandEffect(final BecomesColorlessForestLandEffect } @Override - public boolean apply(Game game, Ability source) { - return false; + public BecomesColorlessForestLandEffect copy() { + return new BecomesColorlessForestLandEffect(this); } @Override - public BecomesColorlessForestLandEffect copy() { - return new BecomesColorlessForestLandEffect(this); + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; + switch (layer) { + case ColorChangingEffects_5: + permanent.getColor(game).setColor(ObjectColor.COLORLESS); + break; + case TypeChangingEffects_4: + permanent.removeAllCardTypes(game); + permanent.addCardType(game, CardType.LAND); + permanent.removeAllSubTypes(game); + permanent.addSubType(game, SubType.FOREST); + permanent.removeAllAbilities(source.getSourceId(), game); + permanent.addAbility(new GreenManaAbility(), source.getSourceId(), game); + break; + } + } } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Permanent enchantment = game.getPermanent(source.getSourceId()); if (enchantment == null || enchantment.getAttachedTo() == null) { return false; @@ -77,26 +96,20 @@ public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) if (permanent == null) { return false; } - switch (layer) { - case ColorChangingEffects_5: - permanent.getColor(game).setWhite(false); - permanent.getColor(game).setGreen(false); - permanent.getColor(game).setBlack(false); - permanent.getColor(game).setBlue(false); - permanent.getColor(game).setRed(false); - break; - case TypeChangingEffects_4: - permanent.removeAllCardTypes(game); - permanent.addCardType(game, CardType.LAND); - permanent.removeAllSubTypes(game); - permanent.addSubType(game, SubType.FOREST); - permanent.removeAllAbilities(source.getSourceId(), game); - permanent.addAbility(new GreenManaAbility(), source.getSourceId(), game); - break; - } + affectedObjects.add(permanent); return true; } + @Override + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + List affectedObjects = new ArrayList<>(); + if (queryAffectedObjects(layer, source, game, affectedObjects)) { + applyToObjects(layer, sublayer, source, game, affectedObjects); + return true; + } + return false; + } + @Override public boolean hasLayer(Layer layer) { return layer == Layer.ColorChangingEffects_5 diff --git a/Mage.Sets/src/mage/cards/t/TheTombOfAclazotz.java b/Mage.Sets/src/mage/cards/t/TheTombOfAclazotz.java index 13faadff1792..be7581a04f42 100644 --- a/Mage.Sets/src/mage/cards/t/TheTombOfAclazotz.java +++ b/Mage.Sets/src/mage/cards/t/TheTombOfAclazotz.java @@ -1,6 +1,7 @@ package mage.cards.t; import mage.MageIdentifier; +import mage.MageItem; import mage.MageObject; import mage.MageObjectReference; import mage.abilities.Ability; @@ -19,14 +20,15 @@ import mage.counters.CounterType; import mage.game.Game; import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; import mage.game.stack.Spell; -import mage.game.stack.StackObject; import mage.target.targetpointer.FixedTarget; import mage.util.CardUtil; import mage.util.SubTypes; import mage.watchers.Watcher; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.UUID; @@ -213,7 +215,7 @@ public boolean applies(GameEvent event, Ability source, Game game) { public boolean replaceEvent(GameEvent event, Ability source, Game game) { Spell target = game.getSpell(event.getSourceId()); if (target != null) { - AddCardSubTypeEnteringTargetEffect effect = new AddCardSubTypeEnteringTargetEffect(mor, subType, Duration.WhileOnBattlefield); + AddCardSubTypeEnteringTargetEffect effect = new AddCardSubTypeEnteringTargetEffect(subType, Duration.WhileOnBattlefield); effect.setTargetPointer(new FixedTarget(target, game)); game.addEffect(effect, source); } @@ -229,44 +231,63 @@ public AddSubtypeEnteringCreatureEffect copy() { class AddCardSubTypeEnteringTargetEffect extends ContinuousEffectImpl { private final SubType addedSubType; - private final MageObjectReference mor; - private Card card; - AddCardSubTypeEnteringTargetEffect(MageObjectReference mor, SubType addedSubType, Duration duration) { + AddCardSubTypeEnteringTargetEffect(SubType addedSubType, Duration duration) { super(duration, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Benefit); this.addedSubType = addedSubType; - this.mor = mor; } protected AddCardSubTypeEnteringTargetEffect(final AddCardSubTypeEnteringTargetEffect effect) { super(effect); this.addedSubType = effect.addedSubType; - this.mor = effect.mor; - this.card = effect.card; } @Override - public boolean apply(Game game, Ability source) { - Spell spell = game.getSpell(getTargetPointer().getFirst(game, source)); - MageObject target = game.getObject(getTargetPointer().getFirst(game, source)); - if (spell != null) { - card = spell.getCard(); + public void init(Ability source, Game game) { + super.init(source, game); + if (getAffectedObjectsSet()) { + Spell spell = game.getSpell(getTargetPointer().getFirst(game, source)); + if (spell != null) { + Card card = spell.getCard(); + // set a mage object reference for the permanent on the battlefield + // target pointer will be used to the find the spell on the stack + MageObjectReference mor = new MageObjectReference(card, game, 1); + affectedObjectList.add(mor); + } } - for (StackObject stackObject : game.getStack()) { - if (stackObject instanceof Spell - && target != null - && target.equals(stackObject) - && mor.refersTo(target, game)) { - setCreatureSubtype(stackObject, addedSubType, game); - setCreatureSubtype(((Spell) stackObject).getCard(), addedSubType, game); + } + + @Override + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + if (object instanceof Spell) { + Spell spell = (Spell) object; + setCreatureSubtype(spell, addedSubType, game); + setCreatureSubtype(spell.getCard(), addedSubType, game); + } else { + Permanent permanent = (Permanent) object; + setCreatureSubtype(permanent, addedSubType, game); } } - if (card != null - && game.getPermanent(card.getId()) != null - && game.getState().getZoneChangeCounter(card.getId()) == mor.getZoneChangeCounter() + 1) { // blinking, etc - game.getPermanent(card.getId()).addSubType(game, addedSubType); + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + MageObject target = game.getSpell(getTargetPointer().getFirst(game, source)); + if (target == null) { + for (MageObjectReference mor : affectedObjectList) { + target = mor.getPermanent(game); + if (target != null) { + break; + } + } } - return true; + if (target != null) { + affectedObjects.add(target); + return true; + } + this.discard(); + return false; } private void setCreatureSubtype(MageObject object, SubType subtype, Game game) { diff --git a/Mage.Sets/src/mage/cards/t/ThranWeaponry.java b/Mage.Sets/src/mage/cards/t/ThranWeaponry.java index 2b6a48cb803c..8192c3723514 100644 --- a/Mage.Sets/src/mage/cards/t/ThranWeaponry.java +++ b/Mage.Sets/src/mage/cards/t/ThranWeaponry.java @@ -1,6 +1,7 @@ package mage.cards.t; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SkipUntapOptionalAbility; @@ -12,9 +13,11 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; +import mage.constants.Layer; import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.List; import java.util.UUID; /** @@ -65,16 +68,12 @@ public ThranWeaponryEffect copy() { } @Override - public boolean apply(Game game, Ability source) { - Permanent ThranWeaponry = game.getPermanent(source.getSourceId()); - if (ThranWeaponry != null) { - if (ThranWeaponry.isTapped()) { - super.apply(game, source); - return true; - } else { - used = true; - } + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + Permanent thranWeaponry = game.getPermanent(source.getSourceId()); + if (thranWeaponry == null || !thranWeaponry.isTapped()) { + this.discard(); + return false; } - return false; + return super.queryAffectedObjects(layer, source, game, affectedObjects); } } diff --git a/Mage.Sets/src/mage/cards/t/TideShaper.java b/Mage.Sets/src/mage/cards/t/TideShaper.java index 9f5f6af0fe1b..8530462aaaa4 100644 --- a/Mage.Sets/src/mage/cards/t/TideShaper.java +++ b/Mage.Sets/src/mage/cards/t/TideShaper.java @@ -1,6 +1,7 @@ package mage.cards.t; import mage.MageInt; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; @@ -15,14 +16,13 @@ import mage.abilities.keyword.KickerAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.SubType; -import mage.constants.TargetController; +import mage.constants.*; import mage.filter.FilterPermanent; import mage.game.Game; +import mage.game.permanent.Permanent; import mage.target.common.TargetLandPermanent; +import java.util.List; import java.util.UUID; /** @@ -98,11 +98,17 @@ public void init(Ability source, Game game) { } @Override - public boolean apply(Game game, Ability source) { + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { if (source.getSourcePermanentIfItStillExists(game) == null) { + this.discard(); + return false; + } + Permanent land = game.getPermanent(this.getTargetPointer().getFirst(game, source)); + if (land == null) { discard(); return false; } - return super.apply(game, source); + affectedObjects.add(land); + return true; } } diff --git a/Mage.Sets/src/mage/cards/u/UnctussRetrofitter.java b/Mage.Sets/src/mage/cards/u/UnctussRetrofitter.java index efc25803c304..cb9e95c7a883 100644 --- a/Mage.Sets/src/mage/cards/u/UnctussRetrofitter.java +++ b/Mage.Sets/src/mage/cards/u/UnctussRetrofitter.java @@ -1,6 +1,7 @@ package mage.cards.u; import mage.MageInt; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.effects.common.continuous.BecomesCreatureTargetEffect; @@ -14,6 +15,7 @@ import mage.game.permanent.token.custom.CreatureToken; import mage.target.TargetPermanent; +import java.util.List; import java.util.UUID; public class UnctussRetrofitter extends CardImpl { @@ -65,12 +67,11 @@ public UnctussRetrofitterBecomesCreatureEffect copy() { } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - Permanent sourcePermanent = source.getSourcePermanentIfItStillExists(game); - if (sourcePermanent == null) { + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + if (game.getPermanent(source.getSourceId()) == null) { this.discard(); return false; } - return super.apply(layer, sublayer, source, game); + return super.queryAffectedObjects(layer, source, game, affectedObjects); } } diff --git a/Mage.Sets/src/mage/cards/x/XolatoyacTheSmilingFlood.java b/Mage.Sets/src/mage/cards/x/XolatoyacTheSmilingFlood.java index 994b6563d3f4..cb43335216d7 100644 --- a/Mage.Sets/src/mage/cards/x/XolatoyacTheSmilingFlood.java +++ b/Mage.Sets/src/mage/cards/x/XolatoyacTheSmilingFlood.java @@ -1,16 +1,16 @@ package mage.cards.x; -import java.util.UUID; import mage.MageInt; +import mage.MageItem; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.abilities.common.EntersBattlefieldOrAttacksSourceTriggeredAbility; import mage.abilities.effects.common.UntapAllEffect; import mage.abilities.effects.common.continuous.BecomesBasicLandTargetEffect; import mage.abilities.effects.common.counter.AddCountersTargetEffect; -import mage.constants.*; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.*; import mage.counters.CounterType; import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledPermanent; @@ -19,6 +19,9 @@ import mage.game.permanent.Permanent; import mage.target.common.TargetLandPermanent; +import java.util.List; +import java.util.UUID; + /** * * @author Grath @@ -81,12 +84,13 @@ public XolatoyacTheSmilingFloodEffect copy() { } @Override - public boolean apply(Game game, Ability source) { + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Permanent land = game.getPermanent(this.getTargetPointer().getFirst(game, source)); if (land == null || land.getCounters(game).getCount(CounterType.FLOOD) < 1) { discard(); return false; } - return super.apply(game, source); + affectedObjects.add(land); + return true; } } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/EnduringGlimmerTriggeredAbilityTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/EnduringGlimmerTriggeredAbilityTest.java new file mode 100644 index 000000000000..3a592b7228b7 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/EnduringGlimmerTriggeredAbilityTest.java @@ -0,0 +1,43 @@ +package org.mage.test.cards.triggers; + +import mage.abilities.keyword.HasteAbility; +import mage.constants.CardType; +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +public class EnduringGlimmerTriggeredAbilityTest extends CardTestPlayerBase { + // Enchantment Creature - Dog Glimmer - 3/3 + // Whenever another creature you control enters, it gets +2/+0 and gains haste until end of turn. + // When Enduring Courage dies, if it was a creature, return it to the battlefield under its owner's control. It's an enchantment. + static String courage = "Enduring Courage"; + // Deal 3 damage to any target + static String bolt = "Lightning Bolt"; + // Creature - Bear - 2/2 + static String cub = "Bear Cub"; + + @Test + public void testEnduringCourage() { + setStrictChooseMode(true); + + addCard(Zone.BATTLEFIELD, playerA, courage); + addCard(Zone.HAND, playerA, bolt); + addCard(Zone.HAND, playerA, cub); + addCard(Zone.BATTLEFIELD, playerA, "Taiga", 3); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, cub); + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN); + + checkAbility("Bear Cub has haste", 1, PhaseStep.PRECOMBAT_MAIN, playerA, cub, HasteAbility.class, true); + checkPT("Bear Cub has +2/+0", 1, PhaseStep.PRECOMBAT_MAIN, playerA, cub, 2 + 2, 2); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, bolt, courage); + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN); + + checkType("Courage is just an enchantment",1, PhaseStep.PRECOMBAT_MAIN, playerA, courage, CardType.CREATURE, false); + + setStopAt(1, PhaseStep.END_TURN); + execute(); + } +} diff --git a/Mage/src/main/java/mage/abilities/common/AnimateDeadTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/AnimateDeadTriggeredAbility.java index f81d85be9133..7e11167725e6 100644 --- a/Mage/src/main/java/mage/abilities/common/AnimateDeadTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/AnimateDeadTriggeredAbility.java @@ -1,5 +1,6 @@ package mage.abilities.common; +import mage.MageItem; import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.DelayedTriggeredAbility; @@ -99,38 +100,52 @@ public void init(Ability source, Game game) { } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - Permanent permanent = affectedObjectList.get(0).getPermanent(game); - if (permanent == null) { - discard(); - return true; + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + for (MageObjectReference mor : affectedObjectList) { + Permanent permanent = mor.getPermanent(game); + if (permanent != null) { + affectedObjects.add(permanent); + } } - switch (layer) { - case TypeChangingEffects_4: - if (becomesAura) { - permanent.addSubType(game, SubType.AURA); - } - break; - case AbilityAddingRemovingEffects_6: - if (!becomesAura) { - List toRemove = new ArrayList<>(); - for (Ability ability : permanent.getAbilities(game)) { - if (ability instanceof EnchantAbility && - ability.getRule().equals("Enchant creature card in a graveyard")) { - toRemove.add(ability); + return !affectedObjects.isEmpty(); + } + + @Override + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; + switch (layer) { + case TypeChangingEffects_4: + if (becomesAura) { + permanent.addSubType(game, SubType.AURA); + } + break; + case AbilityAddingRemovingEffects_6: + if (!becomesAura) { + List toRemove = new ArrayList<>(); + for (Ability ability : permanent.getAbilities(game)) { + if (ability instanceof EnchantAbility && + ability.getRule().equals("Enchant creature card in a graveyard")) { + toRemove.add(ability); + } } + permanent.removeAbilities(toRemove, source.getSourceId(), game); } - permanent.removeAbilities(toRemove, source.getSourceId(), game); - } - permanent.addAbility(newAbility, source.getSourceId(), game); - permanent.getSpellAbility().getTargets().clear(); - permanent.getSpellAbility().getTargets().add(newTarget); + permanent.addAbility(newAbility, source.getSourceId(), game); + permanent.getSpellAbility().getTargets().clear(); + permanent.getSpellAbility().getTargets().add(newTarget); + } } - return true; } @Override - public boolean apply(Game game, Ability source) { + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + List affectedObjects = new ArrayList<>(); + if (queryAffectedObjects(layer, source, game, affectedObjects)) { + applyToObjects(layer, sublayer, source, game, affectedObjects); + return true; + } + this.discard(); return false; } diff --git a/Mage/src/main/java/mage/abilities/common/EnduringGlimmerTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/EnduringGlimmerTriggeredAbility.java index acf578c8e870..c9ce16e1f6e2 100644 --- a/Mage/src/main/java/mage/abilities/common/EnduringGlimmerTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/EnduringGlimmerTriggeredAbility.java @@ -1,5 +1,6 @@ package mage.abilities.common; +import mage.MageItem; import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffectImpl; @@ -11,6 +12,8 @@ import mage.players.Player; import mage.target.targetpointer.FixedTarget; +import java.util.List; + /** * @author TheElk801, PurpleCrowbar */ @@ -80,16 +83,35 @@ public EnduringGlimmerTypeEffect copy() { return new EnduringGlimmerTypeEffect(this); } + @Override - public boolean apply(Game game, Ability source) { + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); - if (permanent == null) { + if (permanent != null) { + affectedObjects.add(permanent); + } + return !affectedObjects.isEmpty(); + } + + @Override + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; + permanent.retainAllEnchantmentSubTypes(game); + permanent.removeAllCardTypes(game); + permanent.addCardType(game, CardType.ENCHANTMENT); + } + } + + @Override + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + if (this.layer != layer && this.sublayer != sublayer) { + return false; + } + if (!super.apply(layer, sublayer, source, game)) { discard(); return false; } - permanent.retainAllEnchantmentSubTypes(game); - permanent.removeAllCardTypes(game); - permanent.addCardType(game, CardType.ENCHANTMENT); return true; } } diff --git a/Mage/src/main/java/mage/abilities/common/GiveManaAbilityAndCastSourceAbility.java b/Mage/src/main/java/mage/abilities/common/GiveManaAbilityAndCastSourceAbility.java index 029b4fc406ce..e6fed3b9129d 100644 --- a/Mage/src/main/java/mage/abilities/common/GiveManaAbilityAndCastSourceAbility.java +++ b/Mage/src/main/java/mage/abilities/common/GiveManaAbilityAndCastSourceAbility.java @@ -1,5 +1,6 @@ package mage.abilities.common; +import mage.MageItem; import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.ActivatedAbilityImpl; @@ -101,38 +102,56 @@ public GainManaAbilitiesWhileExiledEffect copy() { } @Override - public boolean apply(Game game, Ability source) { + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); + if (permanent != null) { + affectedObjects.add(permanent); + } + return !affectedObjects.isEmpty(); + } + + @Override + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; + for (char c : colors.toCharArray()) { + Ability ability; + switch (c) { + case 'W': + ability = new WhiteManaAbility(); + break; + case 'U': + ability = new BlueManaAbility(); + break; + case 'B': + ability = new BlackManaAbility(); + break; + case 'R': + ability = new RedManaAbility(); + break; + case 'G': + ability = new GreenManaAbility(); + break; + default: + continue; + } + permanent.addAbility(ability, source.getSourceId(), game); + } + } + } + + @Override + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { if (WasCastFromExileWatcher.check((MageObjectReference) getValue("exiledHandCardRef"), game)) { discard(); return false; } - Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); - if (permanent == null) { - discard(); + if (this.layer != layer && this.sublayer != sublayer) { return false; } - for (char c : colors.toCharArray()) { - Ability ability; - switch (c) { - case 'W': - ability = new WhiteManaAbility(); - break; - case 'U': - ability = new BlueManaAbility(); - break; - case 'B': - ability = new BlackManaAbility(); - break; - case 'R': - ability = new RedManaAbility(); - break; - case 'G': - ability = new GreenManaAbility(); - break; - default: - continue; - } - permanent.addAbility(ability, source.getSourceId(), game); + if (!super.apply(layer, sublayer, source, game)) { + discard(); + return false; } return true; } diff --git a/Mage/src/main/java/mage/abilities/common/LicidAbility.java b/Mage/src/main/java/mage/abilities/common/LicidAbility.java index 2c84fe047877..6600b39b9d97 100644 --- a/Mage/src/main/java/mage/abilities/common/LicidAbility.java +++ b/Mage/src/main/java/mage/abilities/common/LicidAbility.java @@ -1,5 +1,7 @@ package mage.abilities.common; +import mage.MageItem; +import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.ActivatedAbilityImpl; import mage.abilities.SpecialAction; @@ -97,14 +99,29 @@ class LicidContinuousEffect extends ContinuousEffectImpl { } @Override - public boolean apply(Game game, Ability source) { - return false; + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + if (layer == Layer.TypeChangingEffects_4) { + affectedObjectList.clear(); + Permanent permanent = source.getSourcePermanentIfItStillExists(game); + if (permanent != null) { + affectedObjects.add(permanent); + affectedObjectList.add(new MageObjectReference(permanent, game)); + } + } else { + for (MageObjectReference mor : affectedObjectList) { + Permanent permanent = mor.getPermanent(game); + if (permanent != null) { + affectedObjects.add(permanent); + } + } + } + return !affectedObjects.isEmpty(); } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - Permanent licid = source.getSourcePermanentIfItStillExists(game); - if (licid != null) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent licid = (Permanent) object; switch (layer) { case TypeChangingEffects_4: licid.removeAllCardTypes(game); @@ -131,9 +148,17 @@ public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) licid.getSpellAbility().getTargets().clear(); licid.getSpellAbility().getTargets().add(target); } + } + } + + @Override + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + ArrayList affectedObjects = new ArrayList<>(); + if (queryAffectedObjects(layer, source, game, affectedObjects)) { + applyToObjects(layer, sublayer, source, game, affectedObjects); return true; } - discard(); + this.discard(); return false; } diff --git a/Mage/src/main/java/mage/abilities/common/MaxSpeedAbility.java b/Mage/src/main/java/mage/abilities/common/MaxSpeedAbility.java index 7f308bb05e20..9a4b6287de45 100644 --- a/Mage/src/main/java/mage/abilities/common/MaxSpeedAbility.java +++ b/Mage/src/main/java/mage/abilities/common/MaxSpeedAbility.java @@ -1,5 +1,6 @@ package mage.abilities.common; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.Mode; import mage.abilities.StaticAbility; @@ -15,6 +16,8 @@ import mage.game.permanent.Permanent; import mage.util.CardUtil; +import java.util.List; + /** * @author TheElk801 */ @@ -70,21 +73,29 @@ public MaxSpeedAbilityEffect copy() { } @Override - public boolean apply(Game game, Ability source) { + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { if (ControllerSpeedCount.instance.calculate(game, source, null) < 4) { return false; } Permanent permanent = game.getPermanent(source.getSourceId()); if (permanent != null) { - permanent.addAbility(ability, source.getSourceId(), game); - return true; + affectedObjects.add(permanent); + } else if (game.getCard(source.getSourceId()) != null) { + Card card = game.getCard(source.getSourceId()); + affectedObjects.add(card); } - Card card = game.getCard(source.getSourceId()); - if (card == null) { - return false; + return !affectedObjects.isEmpty(); + } + + @Override + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + if (object instanceof Permanent) { + ((Permanent) object).addAbility(ability, source.getSourceId(), game); + } else { + game.getState().addOtherAbility((Card) object, ability); + } } - game.getState().addOtherAbility(card, ability); - return true; } @Override diff --git a/Mage/src/main/java/mage/abilities/common/SpellTransformedAbility.java b/Mage/src/main/java/mage/abilities/common/SpellTransformedAbility.java index 5adbff755f56..63a0233909c4 100644 --- a/Mage/src/main/java/mage/abilities/common/SpellTransformedAbility.java +++ b/Mage/src/main/java/mage/abilities/common/SpellTransformedAbility.java @@ -1,6 +1,7 @@ package mage.abilities.common; import mage.MageIdentifier; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.SpellAbility; import mage.abilities.costs.mana.ManaCostsImpl; @@ -11,6 +12,7 @@ import mage.game.Game; import mage.game.stack.Spell; +import java.util.List; import java.util.Set; import java.util.UUID; @@ -103,13 +105,19 @@ public TransformedEffect copy() { } @Override - public boolean apply(Game game, Ability source) { + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Spell spell = game.getSpell(source.getSourceId()); - if (spell == null || spell.getCard().getSecondCardFace() == null) { - return false; + if (spell != null && spell.getCard().getSecondCardFace() != null) { + affectedObjects.add(spell); + } + return !affectedObjects.isEmpty(); + } + + @Override + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + // simulate another side as new card (another code part in spell constructor) + TransformAbility.transformCardSpellDynamic((Spell) object, ((Spell) object).getCard().getSecondCardFace(), game); } - // simulate another side as new card (another code part in spell constructor) - TransformAbility.transformCardSpellDynamic(spell, spell.getCard().getSecondCardFace(), game); - return true; } } diff --git a/Mage/src/main/java/mage/abilities/effects/ApplyStatusEffect.java b/Mage/src/main/java/mage/abilities/effects/ApplyStatusEffect.java index 591c3f0153b7..06b5bd14e62b 100644 --- a/Mage/src/main/java/mage/abilities/effects/ApplyStatusEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/ApplyStatusEffect.java @@ -1,17 +1,25 @@ package mage.abilities.effects; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.keyword.MenaceAbility; -import mage.constants.*; +import mage.constants.Duration; +import mage.constants.Layer; +import mage.constants.Outcome; +import mage.constants.SubLayer; import mage.counters.AbilityCounter; import mage.counters.BoostCounter; +import mage.counters.Counters; import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.ArrayList; +import java.util.List; + /** * @author BetaSteward_at_googlemail.com *

- * Applies boost from from boost counters and also adds abilities from ability counters and suspected mechanic + * Applies boost from boost counters and also adds abilities from ability counters and suspected mechanic */ public class ApplyStatusEffect extends ContinuousEffectImpl { @@ -24,14 +32,21 @@ private ApplyStatusEffect(ApplyStatusEffect effect) { } @Override - public boolean apply(Game game, Ability source) { - return false; + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + for (Permanent permanent : game.getBattlefield().getAllActivePermanents()) { + Counters counters = permanent.getCounters(game); + if (!counters.getAbilityCounters().isEmpty() || !counters.getBoostCounters().isEmpty()) { + affectedObjects.add(permanent); + } + } + return !affectedObjects.isEmpty(); } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { if (layer == Layer.AbilityAddingRemovingEffects_6) { - for (Permanent permanent : game.getBattlefield().getAllActivePermanents()) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; for (AbilityCounter counter : permanent.getCounters(game).getAbilityCounters()) { permanent.addAbility(counter.getAbility(), source == null ? permanent.getId() : source.getSourceId(), game); } @@ -41,14 +56,24 @@ public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) } } if (layer == Layer.PTChangingEffects_7 && sublayer == SubLayer.Counters_7d) { - for (Permanent permanent : game.getBattlefield().getAllActivePermanents(CardType.CREATURE, game)) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; for (BoostCounter counter : permanent.getCounters(game).getBoostCounters()) { permanent.addPower(counter.getPower() * counter.getCount()); permanent.addToughness(counter.getToughness() * counter.getCount()); } } } - return true; + } + + @Override + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + List affectedObjects = new ArrayList<>(); + if (queryAffectedObjects(layer, source, game, affectedObjects)) { + applyToObjects(layer, sublayer, source, game, affectedObjects); + return true; + } + return false; } @Override diff --git a/Mage/src/main/java/mage/abilities/effects/ContinuousEffect.java b/Mage/src/main/java/mage/abilities/effects/ContinuousEffect.java index c1456292c371..46728481b3ee 100644 --- a/Mage/src/main/java/mage/abilities/effects/ContinuousEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/ContinuousEffect.java @@ -1,5 +1,6 @@ package mage.abilities.effects; +import mage.MageItem; import mage.MageObjectReference; import mage.abilities.Ability; import mage.constants.DependencyType; @@ -9,10 +10,7 @@ import mage.game.Game; import mage.target.targetpointer.TargetPointer; -import java.util.EnumSet; -import java.util.List; -import java.util.Set; -import java.util.UUID; +import java.util.*; /** * @author BetaSteward_at_googlemail.com @@ -35,6 +33,18 @@ public interface ContinuousEffect extends Effect { boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game); + /** + * Applies the effect to the passed in list of objects. This method should only contain logic for applying to + * the objects. All object filtering should be done in {@link #queryAffectedObjects} before passing to this function. + */ + void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects); + + /** + * Gathers all objects the effect should apply to. Do all filtering logic in this function to avoid errors in {@link #applyToObjects}. + * @return true if adding any objects to the affectedObjects list, otherwise return false + */ + boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects); + boolean hasLayer(Layer layer); boolean isInactive(Ability source, Game game); diff --git a/Mage/src/main/java/mage/abilities/effects/ContinuousEffectImpl.java b/Mage/src/main/java/mage/abilities/effects/ContinuousEffectImpl.java index c8a5b78dd0e4..702a442d4746 100644 --- a/Mage/src/main/java/mage/abilities/effects/ContinuousEffectImpl.java +++ b/Mage/src/main/java/mage/abilities/effects/ContinuousEffectImpl.java @@ -1,5 +1,6 @@ package mage.abilities.effects; +import mage.MageItem; import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.CompoundAbility; @@ -115,8 +116,32 @@ public Duration getDuration() { @Override public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { if (this.layer == layer && this.sublayer == sublayer) { - return apply(game, source); + List affectedObjects = new ArrayList<>(); + if (queryAffectedObjects(layer, source, game, affectedObjects)) { + applyToObjects(layer, sublayer, source, game, affectedObjects); + return true; + } else { + return apply(game, source); + } + } + return false; + } + + @Override + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + return false; + } + + @Override + public boolean apply(Game game, Ability source) { + // Do nothing in new query logic and override in old apply logic return false; } diff --git a/Mage/src/main/java/mage/abilities/effects/ContinuousEffects.java b/Mage/src/main/java/mage/abilities/effects/ContinuousEffects.java index a60322ba64ab..2054b263cab2 100644 --- a/Mage/src/main/java/mage/abilities/effects/ContinuousEffects.java +++ b/Mage/src/main/java/mage/abilities/effects/ContinuousEffects.java @@ -966,6 +966,7 @@ public boolean replaceEvent(GameEvent event, Game game) { //20091005 - 613 public synchronized void apply(Game game) { removeInactiveEffects(game); + List activeLayerEffects = getLayeredEffects(game); // main call List layer = filterLayeredEffects(activeLayerEffects, Layer.CopyEffects_1); diff --git a/Mage/src/main/java/mage/abilities/effects/common/CopyEffect.java b/Mage/src/main/java/mage/abilities/effects/common/CopyEffect.java index eaadf209ab40..56b6a43bc6ad 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/CopyEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/CopyEffect.java @@ -1,5 +1,6 @@ package mage.abilities.effects.common; +import mage.MageItem; import mage.MageObject; import mage.MageObjectReference; import mage.abilities.Ability; @@ -13,6 +14,7 @@ import mage.util.CardUtil; import mage.util.functions.CopyApplier; +import java.util.List; import java.util.UUID; /** @@ -56,7 +58,10 @@ public void init(Ability source, Game game) { Permanent permanent = game.getPermanent(copyToObjectId); if (permanent != null) { - affectedObjectList.add(new MageObjectReference(permanent, game)); + MageObjectReference mor = new MageObjectReference(permanent, game); + if (!affectedObjectList.contains(mor)) { + affectedObjectList.add(mor); + } } else if (source.getAbilityType() == AbilityType.STATIC) { // for replacement effects that let a permanent enter the battlefield as a copy of another permanent we need to apply that copy // before the permanent is added to the battlefield @@ -68,34 +73,43 @@ public void init(Ability source, Game game) { if (permanent instanceof PermanentToken) { ZCCDiff = 0; } - affectedObjectList.add(new MageObjectReference(permanent.getId(), game.getState().getZoneChangeCounter(copyToObjectId) + ZCCDiff, game)); + MageObjectReference mor = new MageObjectReference(permanent.getId(), game.getState().getZoneChangeCounter(copyToObjectId) + ZCCDiff, game); + if (!affectedObjectList.contains(mor)) { + affectedObjectList.add(mor); + } } } } @Override - public boolean apply(Game game, Ability source) { - if (affectedObjectList.isEmpty()) { - this.discard(); - return false; - } - Permanent permanent = affectedObjectList.get(0).getPermanent(game); - if (permanent == null) { - if (!game.checkShortLivingLKI(getSourceId(), Zone.BATTLEFIELD)) { - discard(); - return false; - } - // As long as the permanent is still in the short living LKI continue to copy to get triggered abilities to TriggeredAbilities for dies events. - permanent = (Permanent) game.getLastKnownInformation(getSourceId(), Zone.BATTLEFIELD, source.getSourceObjectZoneChangeCounter()); + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + for (MageObjectReference mor : affectedObjectList) { + Permanent permanent = mor.getPermanent(game); if (permanent == null) { - discard(); - return false; + if (!game.checkShortLivingLKI(getSourceId(), Zone.BATTLEFIELD)) { + this.discard(); + return false; + } + // As long as the permanent is still in the short living LKI continue to copy to get triggered abilities to TriggeredAbilities for dies events. + permanent = (Permanent) game.getLastKnownInformation(getSourceId(), Zone.BATTLEFIELD, source.getSourceObjectZoneChangeCounter()); + if (permanent == null) { + this.discard(); + return false; + } } + affectedObjects.add(permanent); + } + return !affectedObjects.isEmpty(); + } + + @Override + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + copyToPermanent((Permanent) object, game, source); } - return copyToPermanent(permanent, game, source); } - protected boolean copyToPermanent(Permanent permanent, Game game, Ability source) { + protected void copyToPermanent(Permanent permanent, Game game, Ability source) { if (copyFromObject.getCopyFrom() != null) { // copy from temp blueprints (they are already copies) permanent.setCopy(true, copyFromObject.getCopyFrom()); @@ -155,7 +169,6 @@ protected boolean copyToPermanent(Permanent permanent, Game game, Ability source CardUtil.copySetAndCardNumber(permanent, copyFromObject); - return true; } @Override diff --git a/Mage/src/main/java/mage/abilities/effects/common/CopyTokenEffect.java b/Mage/src/main/java/mage/abilities/effects/common/CopyTokenEffect.java index 4a9f5082214b..0d66eed0f624 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/CopyTokenEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/CopyTokenEffect.java @@ -1,5 +1,6 @@ package mage.abilities.effects.common; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffectImpl; import mage.constants.*; @@ -7,6 +8,8 @@ import mage.game.permanent.Permanent; import mage.game.permanent.token.Token; +import java.util.List; + public class CopyTokenEffect extends ContinuousEffectImpl { protected Token token; @@ -23,30 +26,38 @@ protected CopyTokenEffect(final CopyTokenEffect effect) { } @Override - public boolean apply(Game game, Ability source) { + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Permanent permanent = game.getPermanent(source.getSourceId()); - permanent.setName(token.getName()); - permanent.getColor(game).setColor(token.getColor(game)); - permanent.removeAllCardTypes(game); - for (CardType type : token.getCardType(game)) { - permanent.addCardType(game, type); - } - permanent.removeAllSubTypes(game); - permanent.copySubTypesFrom(game, token); - permanent.removeAllSuperTypes(game); - for (SuperType type : token.getSuperType(game)) { - permanent.addSuperType(game, type); + if (permanent != null) { + affectedObjects.add(permanent); } - permanent.getAbilities().clear(); - for (Ability ability : token.getAbilities()) { - permanent.addAbility(ability, source.getSourceId(), game, true); - } - permanent.getPower().setModifiedBaseValue(token.getPower().getModifiedBaseValue()); - permanent.getToughness().setModifiedBaseValue(token.getToughness().getModifiedBaseValue()); - //permanent.getLoyalty().setBoostedValue(card.getLoyalty().getValue()); - - return true; + return !affectedObjects.isEmpty(); + } + @Override + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; + permanent.setName(token.getName()); + permanent.getColor(game).setColor(token.getColor(game)); + permanent.removeAllCardTypes(game); + for (CardType type : token.getCardType(game)) { + permanent.addCardType(game, type); + } + permanent.removeAllSubTypes(game); + permanent.copySubTypesFrom(game, token); + permanent.removeAllSuperTypes(game); + for (SuperType type : token.getSuperType(game)) { + permanent.addSuperType(game, type); + } + permanent.getAbilities().clear(); + for (Ability ability : token.getAbilities()) { + permanent.addAbility(ability, source.getSourceId(), game, true); + } + permanent.getPower().setModifiedBaseValue(token.getPower().getModifiedBaseValue()); + permanent.getToughness().setModifiedBaseValue(token.getToughness().getModifiedBaseValue()); + //permanent.getLoyalty().setBoostedValue(card.getLoyalty().getValue()); + } } @Override diff --git a/Mage/src/main/java/mage/abilities/effects/common/GainActivatedAbilitiesOfTopCardEffect.java b/Mage/src/main/java/mage/abilities/effects/common/GainActivatedAbilitiesOfTopCardEffect.java index 9a90760ce479..b9bb487d9864 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/GainActivatedAbilitiesOfTopCardEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/GainActivatedAbilitiesOfTopCardEffect.java @@ -1,5 +1,6 @@ package mage.abilities.effects.common; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffectImpl; import mage.cards.Card; @@ -12,6 +13,8 @@ import mage.game.permanent.Permanent; import mage.players.Player; +import java.util.List; + public class GainActivatedAbilitiesOfTopCardEffect extends ContinuousEffectImpl { private final FilterCard filter; @@ -33,23 +36,33 @@ public GainActivatedAbilitiesOfTopCardEffect copy() { } @Override - public boolean apply(Game game, Ability source) { + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Player player = game.getPlayer(source.getControllerId()); - if (player != null) { + if (player == null) { + return false; + } + Card card = player.getLibrary().getFromTop(game); + if (card == null || !filter.match(card, game)) { + return false; + } + Permanent permanent = game.getPermanent(source.getSourceId()); + if (permanent != null) { + affectedObjects.add(permanent); + } + return !affectedObjects.isEmpty(); + } + + @Override + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Player player = game.getPlayer(source.getControllerId()); Card card = player.getLibrary().getFromTop(game); - if (filter.match(card, game)) { - Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent != null) { - for (Ability ability : card.getAbilities(game)) { - if (ability.isActivatedAbility()) { - permanent.addAbility(ability, source.getSourceId(), game, true); - } - } - return true; + Permanent permanent = (Permanent) object; + for (Ability ability : card.getAbilities(game)) { + if (ability.isActivatedAbility()) { + permanent.addAbility(ability, source.getSourceId(), game, true); } } } - return false; } - } diff --git a/Mage/src/main/java/mage/abilities/effects/common/combat/CanBlockAdditionalCreatureAllEffect.java b/Mage/src/main/java/mage/abilities/effects/common/combat/CanBlockAdditionalCreatureAllEffect.java index 3e815aa31bbe..aa156b956263 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/combat/CanBlockAdditionalCreatureAllEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/combat/CanBlockAdditionalCreatureAllEffect.java @@ -1,6 +1,7 @@ package mage.abilities.effects.common.combat; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffectImpl; import mage.constants.Duration; @@ -12,6 +13,8 @@ import mage.game.permanent.Permanent; import mage.util.CardUtil; +import java.util.List; + /** * @author emerald000 */ @@ -22,7 +25,7 @@ public class CanBlockAdditionalCreatureAllEffect extends ContinuousEffectImpl { protected FilterPermanent filter; public CanBlockAdditionalCreatureAllEffect(int amount, FilterPermanent filter, Duration duration) { - super(duration, Outcome.Benefit); + super(duration, Layer.RulesEffects, SubLayer.NA, Outcome.Benefit); this.amount = amount; this.filter = filter; staticText = setText(); @@ -40,25 +43,24 @@ public CanBlockAdditionalCreatureAllEffect copy() { } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game)) { - if (permanent != null) { - // maxBlocks = 0 equals to "can block any number of creatures" - if (amount > 0) { - if (permanent.getMaxBlocks() > 0) { - permanent.setMaxBlocks(permanent.getMaxBlocks() + amount); - } - } else { - permanent.setMaxBlocks(0); + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; + // maxBlocks = 0 equals to "can block any number of creatures" + if (amount > 0) { + if (permanent.getMaxBlocks() > 0) { + permanent.setMaxBlocks(permanent.getMaxBlocks() + amount); } + } else { + permanent.setMaxBlocks(amount); } } - return true; } @Override - public boolean apply(Game game, Ability source) { - return false; + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + affectedObjects.addAll(game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game)); + return !affectedObjects.isEmpty(); } private String setText() { @@ -77,9 +79,4 @@ private String setText() { } return sb.toString(); } - - @Override - public boolean hasLayer(Layer layer) { - return layer == Layer.RulesEffects; - } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/combat/CanBlockAdditionalCreatureEffect.java b/Mage/src/main/java/mage/abilities/effects/common/combat/CanBlockAdditionalCreatureEffect.java index a2630e7b7e43..4f9da4aac91c 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/combat/CanBlockAdditionalCreatureEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/combat/CanBlockAdditionalCreatureEffect.java @@ -1,6 +1,7 @@ package mage.abilities.effects.common.combat; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffectImpl; import mage.constants.Duration; @@ -11,6 +12,8 @@ import mage.game.permanent.Permanent; import mage.util.CardUtil; +import java.util.List; + /** * @author LevelX2 */ @@ -32,7 +35,7 @@ public CanBlockAdditionalCreatureEffect(int amount) { } public CanBlockAdditionalCreatureEffect(Duration duration, int amount) { - super(duration, Outcome.Benefit); + super(duration, Layer.RulesEffects, SubLayer.NA, Outcome.Benefit); this.amount = amount; staticText = setText(); } @@ -48,9 +51,9 @@ public CanBlockAdditionalCreatureEffect copy() { } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent != null) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; // maxBlocks = 0 equals to "can block any number of creatures" if (amount > 0) { if (permanent.getMaxBlocks() > 0) { @@ -59,13 +62,16 @@ public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) } else { permanent.setMaxBlocks(0); } - return true; } - return false; } @Override - public boolean apply(Game game, Ability source) { + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + Permanent permanent = game.getPermanent(source.getSourceId()); + if (permanent != null) { + affectedObjects.add(permanent); + return true; + } return false; } @@ -87,9 +93,4 @@ private String setText() { return sb.toString(); } - @Override - public boolean hasLayer(Layer layer) { - return layer == Layer.RulesEffects; - } - } diff --git a/Mage/src/main/java/mage/abilities/effects/common/combat/CanBlockAdditionalCreatureTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/combat/CanBlockAdditionalCreatureTargetEffect.java index 77011abb9a93..f627ce1d49f8 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/combat/CanBlockAdditionalCreatureTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/combat/CanBlockAdditionalCreatureTargetEffect.java @@ -1,5 +1,6 @@ package mage.abilities.effects.common.combat; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffectImpl; import mage.constants.Duration; @@ -9,6 +10,8 @@ import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.List; + /** * @author mzulch */ @@ -30,7 +33,7 @@ public CanBlockAdditionalCreatureTargetEffect() { * @param amount 0 = any number */ public CanBlockAdditionalCreatureTargetEffect(Duration duration, int amount) { - super(duration, Outcome.Benefit); + super(duration, Layer.RulesEffects, SubLayer.NA, Outcome.Benefit); this.amount = amount; } @@ -45,31 +48,27 @@ public CanBlockAdditionalCreatureTargetEffect copy() { } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - Permanent target = game.getPermanent(this.getTargetPointer().getFirst(game, source)); - if (target == null) { - return false; - } - - // maxBlocks = 0 equals to "can block any number of creatures" - if (amount > 0) { - if (target.getMaxBlocks() > 0) { - target.setMaxBlocks(target.getMaxBlocks() + amount); + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; + // maxBlocks = 0 equals to "can block any number of creatures" + if (amount > 0) { + if (permanent.getMaxBlocks() > 0) { + permanent.setMaxBlocks(permanent.getMaxBlocks() + amount); + } + } else { + permanent.setMaxBlocks(0); } - } else { - target.setMaxBlocks(0); } - - return true; } @Override - public boolean apply(Game game, Ability source) { + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + Permanent target = game.getPermanent(this.getTargetPointer().getFirst(game, source)); + if (target != null) { + affectedObjects.add(target); + return true; + } return false; } - - @Override - public boolean hasLayer(Layer layer) { - return layer == Layer.RulesEffects; - } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/combat/CantBeBlockedByMoreThanOneAllEffect.java b/Mage/src/main/java/mage/abilities/effects/common/combat/CantBeBlockedByMoreThanOneAllEffect.java index da18fcfefaf4..2148df0aafd6 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/combat/CantBeBlockedByMoreThanOneAllEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/combat/CantBeBlockedByMoreThanOneAllEffect.java @@ -1,25 +1,26 @@ package mage.abilities.effects.common.combat; +import mage.MageItem; +import mage.abilities.Ability; +import mage.abilities.effects.ContinuousEffectImpl; import mage.constants.Duration; import mage.constants.Layer; import mage.constants.Outcome; import mage.constants.SubLayer; -import mage.abilities.Ability; -import mage.abilities.effects.ContinuousEffectImpl; import mage.filter.FilterPermanent; import mage.game.Game; import mage.game.permanent.Permanent; - - import mage.util.CardUtil; +import java.util.List; + /** * @author Quercitron */ public class CantBeBlockedByMoreThanOneAllEffect extends ContinuousEffectImpl { - private FilterPermanent filter; + private final FilterPermanent filter; protected int amount; public CantBeBlockedByMoreThanOneAllEffect(FilterPermanent filter) { @@ -31,11 +32,11 @@ public CantBeBlockedByMoreThanOneAllEffect(int amount, FilterPermanent filter) { } public CantBeBlockedByMoreThanOneAllEffect(int amount, FilterPermanent filter, Duration duration) { - super(duration, Outcome.Benefit); + super(duration, Layer.RulesEffects, SubLayer.NA, Outcome.Benefit); this.amount = amount; this.filter = filter; - staticText = new StringBuilder("Each ").append(filter.getMessage()).append(" can't be blocked by more than ") - .append(CardUtil.numberToText(amount)).append(" creature").append(amount > 1 ? "s" : "").toString(); + staticText = "Each " + filter.getMessage() + " can't be blocked by more than " + + CardUtil.numberToText(amount) + " creature" + (amount > 1 ? "s" : ""); } protected CantBeBlockedByMoreThanOneAllEffect(final CantBeBlockedByMoreThanOneAllEffect effect) { @@ -50,24 +51,15 @@ public CantBeBlockedByMoreThanOneAllEffect copy() { } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - switch (layer) { - case RulesEffects: - for (Permanent perm : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game)) { - perm.setMaxBlockedBy(amount); - } - break; + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + ((Permanent) object).setMaxBlockedBy(amount); } - return true; - } - - @Override - public boolean apply(Game game, Ability source) { - return false; } @Override - public boolean hasLayer(Layer layer) { - return layer == Layer.RulesEffects; + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + affectedObjects.addAll(game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game)); + return !affectedObjects.isEmpty(); } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/combat/CantBeBlockedByMoreThanOneAttachedEffect.java b/Mage/src/main/java/mage/abilities/effects/common/combat/CantBeBlockedByMoreThanOneAttachedEffect.java index ba33d007780f..e499e884c9ae 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/combat/CantBeBlockedByMoreThanOneAttachedEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/combat/CantBeBlockedByMoreThanOneAttachedEffect.java @@ -1,5 +1,6 @@ package mage.abilities.effects.common.combat; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffectImpl; import mage.constants.*; @@ -7,6 +8,8 @@ import mage.game.permanent.Permanent; import mage.util.CardUtil; +import java.util.List; + /** * @author LevelX2, edited by Cguy7777 */ @@ -42,12 +45,19 @@ public CantBeBlockedByMoreThanOneAttachedEffect copy() { } @Override - public boolean apply(Game game, Ability source) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + ((Permanent) object).setMaxBlockedBy(amount); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Permanent attachment = game.getPermanent(source.getSourceId()); if (attachment != null && attachment.getAttachedTo() != null) { - Permanent perm = game.getPermanent(attachment.getAttachedTo()); - if (perm != null) { - perm.setMaxBlockedBy(amount); + Permanent permanent = game.getPermanent(attachment.getAttachedTo()); + if (permanent != null) { + affectedObjects.add(permanent); return true; } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/combat/CantBeBlockedByMoreThanOneSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/combat/CantBeBlockedByMoreThanOneSourceEffect.java index f4fbdca9873b..dce414ce8d12 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/combat/CantBeBlockedByMoreThanOneSourceEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/combat/CantBeBlockedByMoreThanOneSourceEffect.java @@ -1,18 +1,19 @@ package mage.abilities.effects.common.combat; +import mage.MageItem; +import mage.abilities.Ability; +import mage.abilities.effects.ContinuousEffectImpl; import mage.constants.Duration; import mage.constants.Layer; import mage.constants.Outcome; import mage.constants.SubLayer; -import mage.abilities.Ability; -import mage.abilities.effects.ContinuousEffectImpl; import mage.game.Game; - - import mage.game.permanent.Permanent; import mage.util.CardUtil; +import java.util.List; + /** * @author Quercitron */ @@ -29,7 +30,7 @@ public CantBeBlockedByMoreThanOneSourceEffect(int amount) { } public CantBeBlockedByMoreThanOneSourceEffect(int amount, Duration duration) { - super(duration, Outcome.Benefit); + super(duration, Layer.RulesEffects, SubLayer.NA, Outcome.Benefit); this.amount = amount; staticText = "{this} can't be blocked by more than " + CardUtil.numberToText(amount) + " creature" + (amount > 1 ? "s" : "") + (duration == Duration.EndOfTurn ? " each combat this turn" : ""); @@ -46,24 +47,19 @@ public CantBeBlockedByMoreThanOneSourceEffect copy() { } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - Permanent perm = game.getPermanent(source.getSourceId()); - if (perm != null) { - if (layer == Layer.RulesEffects) { - perm.setMaxBlockedBy(amount); - } - return true; + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + ((Permanent) object).setMaxBlockedBy(amount); } - return false; } @Override - public boolean apply(Game game, Ability source) { + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + Permanent permanent = game.getPermanent(source.getSourceId()); + if (permanent != null) { + affectedObjects.add(permanent); + return true; + } return false; } - - @Override - public boolean hasLayer(Layer layer) { - return layer == Layer.RulesEffects; - } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/combat/CantBeBlockedByOneAllEffect.java b/Mage/src/main/java/mage/abilities/effects/common/combat/CantBeBlockedByOneAllEffect.java index e649ee0543d5..ad23ce14107b 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/combat/CantBeBlockedByOneAllEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/combat/CantBeBlockedByOneAllEffect.java @@ -1,23 +1,26 @@ package mage.abilities.effects.common.combat; +import mage.MageItem; +import mage.abilities.Ability; +import mage.abilities.effects.ContinuousEffectImpl; import mage.constants.Duration; import mage.constants.Layer; import mage.constants.Outcome; import mage.constants.SubLayer; -import mage.abilities.Ability; -import mage.abilities.effects.ContinuousEffectImpl; import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.game.permanent.Permanent; import mage.util.CardUtil; +import java.util.List; + /** * @author LevelX2 */ public class CantBeBlockedByOneAllEffect extends ContinuousEffectImpl { - private FilterCreaturePermanent filter; + private final FilterCreaturePermanent filter; protected int amount; public CantBeBlockedByOneAllEffect(int amount, FilterCreaturePermanent filter) { @@ -25,7 +28,7 @@ public CantBeBlockedByOneAllEffect(int amount, FilterCreaturePermanent filter) { } public CantBeBlockedByOneAllEffect(int amount, FilterCreaturePermanent filter, Duration duration) { - super(duration, Outcome.Benefit); + super(duration, Layer.RulesEffects, SubLayer.NA, Outcome.Benefit); this.amount = amount; this.filter = filter; StringBuilder sb = new StringBuilder("each ").append(filter.getMessage()).append(" can't be blocked "); @@ -48,24 +51,15 @@ public CantBeBlockedByOneAllEffect copy() { } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - switch (layer) { - case RulesEffects: - for (Permanent perm : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game)) { - perm.setMinBlockedBy(amount); - } - break; + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + ((Permanent) object).setMinBlockedBy(amount); } - return true; - } - - @Override - public boolean apply(Game game, Ability source) { - return false; } @Override - public boolean hasLayer(Layer layer) { - return layer == Layer.RulesEffects; + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + affectedObjects.addAll(game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game)); + return !affectedObjects.isEmpty(); } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/combat/CantBeBlockedByOneAttachedEffect.java b/Mage/src/main/java/mage/abilities/effects/common/combat/CantBeBlockedByOneAttachedEffect.java index 6292e5fc4f9d..d2d46f1ccac9 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/combat/CantBeBlockedByOneAttachedEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/combat/CantBeBlockedByOneAttachedEffect.java @@ -1,16 +1,15 @@ package mage.abilities.effects.common.combat; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffectImpl; -import mage.constants.AttachmentType; -import mage.constants.Duration; -import mage.constants.Layer; -import mage.constants.Outcome; -import mage.constants.SubLayer; +import mage.constants.*; import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.List; + /** * @author LevelX2 */ @@ -24,7 +23,7 @@ public CantBeBlockedByOneAttachedEffect(AttachmentType attachmentType, int amoun } public CantBeBlockedByOneAttachedEffect(AttachmentType attachmentType, int amount, Duration duration) { - super(duration, Outcome.Benefit); + super(duration, Layer.RulesEffects, SubLayer.NA, Outcome.Benefit); this.amount = amount; this.attachmentType = attachmentType; staticText = attachmentType.verb() + " creature can't be blocked except by " + amount + " or more creatures"; @@ -42,29 +41,22 @@ public CantBeBlockedByOneAttachedEffect copy() { } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - switch (layer) { - case RulesEffects: - Permanent attachment = game.getPermanent(source.getSourceId()); - if (attachment != null && attachment.getAttachedTo() != null) { - Permanent perm = game.getPermanent(attachment.getAttachedTo()); - if (perm != null) { - perm.setMinBlockedBy(amount); - return true; - } - } - break; + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + ((Permanent) object).setMinBlockedBy(amount); } - return false; } @Override - public boolean apply(Game game, Ability source) { + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + Permanent attachment = game.getPermanent(source.getSourceId()); + if (attachment != null && attachment.getAttachedTo() != null) { + Permanent permanent = game.getPermanent(attachment.getAttachedTo()); + if (permanent != null) { + affectedObjects.add(permanent); + return true; + } + } return false; } - - @Override - public boolean hasLayer(Layer layer) { - return layer == Layer.RulesEffects; - } -} \ No newline at end of file +} diff --git a/Mage/src/main/java/mage/abilities/effects/common/combat/CantBeBlockedByOneEffect.java b/Mage/src/main/java/mage/abilities/effects/common/combat/CantBeBlockedByOneEffect.java index 47a0cf7e4eec..02a6d9e6a001 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/combat/CantBeBlockedByOneEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/combat/CantBeBlockedByOneEffect.java @@ -1,5 +1,6 @@ package mage.abilities.effects.common.combat; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffectImpl; import mage.constants.Duration; @@ -10,6 +11,8 @@ import mage.game.permanent.Permanent; import mage.util.CardUtil; +import java.util.List; + /** * @author North */ @@ -38,10 +41,17 @@ public CantBeBlockedByOneEffect copy() { } @Override - public boolean apply(Game game, Ability source) { - Permanent perm = source.getSourcePermanentIfItStillExists(game); - if (perm != null) { - perm.setMinBlockedBy(amount); + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + ((Permanent) object).setMinBlockedBy(amount); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + Permanent permanent = game.getPermanent(source.getSourceId()); + if (permanent != null) { + affectedObjects.add(permanent); return true; } return false; diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/AddBasicLandTypeAllLandsEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddBasicLandTypeAllLandsEffect.java index fb92836067df..9eb836ab71ed 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/AddBasicLandTypeAllLandsEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddBasicLandTypeAllLandsEffect.java @@ -1,5 +1,6 @@ package mage.abilities.effects.common.continuous; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.mana.*; @@ -8,6 +9,8 @@ import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.List; + /** * @author Plopman, TheElk801 */ @@ -52,7 +55,7 @@ public AddBasicLandTypeAllLandsEffect copy() { } @Override - public boolean apply(Game game, Ability source) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { Ability ability; switch (subType) { case PLAINS: @@ -73,9 +76,8 @@ public boolean apply(Game game, Ability source) { default: ability = null; } - for (Permanent land : game.getBattlefield().getActivePermanents( - StaticFilters.FILTER_LAND, source.getControllerId(), game - )) { + for (MageItem object : affectedObjects) { + Permanent land = (Permanent) object; // 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 @@ -84,6 +86,13 @@ public boolean apply(Game game, Ability source) { land.addAbility(ability, source.getSourceId(), game); } } - return true; + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + affectedObjects.addAll(game.getBattlefield().getActivePermanents( + StaticFilters.FILTER_LAND, source.getControllerId(), source, game + )); + return !affectedObjects.isEmpty(); } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardColorAttachedEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardColorAttachedEffect.java index 90bf119753b3..203fdd0f60b1 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardColorAttachedEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardColorAttachedEffect.java @@ -1,5 +1,6 @@ package mage.abilities.effects.common.continuous; +import mage.MageItem; import mage.ObjectColor; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffectImpl; @@ -7,6 +8,8 @@ import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.List; + /** * @author noxx */ @@ -27,24 +30,33 @@ protected AddCardColorAttachedEffect(final AddCardColorAttachedEffect effect) { } @Override - public boolean apply(Game game, Ability source) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent target = (Permanent) object; + if (addedColor.isBlack()) + target.getColor(game).setBlack(true); + if (addedColor.isBlue()) + target.getColor(game).setBlue(true); + if (addedColor.isWhite()) + target.getColor(game).setWhite(true); + if (addedColor.isGreen()) + target.getColor(game).setGreen(true); + if (addedColor.isRed()) + target.getColor(game).setRed(true); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Permanent equipment = game.getPermanent(source.getSourceId()); if (equipment != null && equipment.getAttachedTo() != null) { Permanent target = game.getPermanent(equipment.getAttachedTo()); if (target != null) { - if (addedColor.isBlack()) - target.getColor(game).setBlack(true); - if (addedColor.isBlue()) - target.getColor(game).setBlue(true); - if (addedColor.isWhite()) - target.getColor(game).setWhite(true); - if (addedColor.isGreen()) - target.getColor(game).setGreen(true); - if (addedColor.isRed()) - target.getColor(game).setRed(true); + affectedObjects.add(target); + return true; } } - return true; + return false; } @Override diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardSubTypeSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardSubTypeSourceEffect.java index d3fa4d3f4e95..95bd0a39cb17 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardSubTypeSourceEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardSubTypeSourceEffect.java @@ -1,5 +1,6 @@ package mage.abilities.effects.common.continuous; +import mage.MageItem; import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.Mode; @@ -45,20 +46,31 @@ public void init(Ability source, Game game) { } @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent != null && affectedObjectList.contains(new MageObjectReference(permanent, game))) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; if (!inAddition) { permanent.removeAllCreatureTypes(game); } - for (SubType cardType : addedSubTypes) { - permanent.addSubType(game, cardType); + permanent.addSubType(game, addedSubTypes); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + for (MageObjectReference mor : affectedObjectList) { + Permanent permanent = mor.getPermanent(game); + if (permanent != null) { + affectedObjects.add(permanent); + } + } + if (affectedObjects.isEmpty()) { + if (duration == Duration.Custom) { + this.discard(); } - return true; - } else if (this.getDuration() == Duration.Custom) { - this.discard(); + return false; } - return false; + return true; } @Override diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardSubTypeTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardSubTypeTargetEffect.java index b7388bbed361..fb1423dc5e8e 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardSubTypeTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardSubTypeTargetEffect.java @@ -1,6 +1,7 @@ package mage.abilities.effects.common.continuous; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.Mode; import mage.abilities.effects.ContinuousEffectImpl; @@ -9,6 +10,7 @@ import mage.game.permanent.Permanent; import mage.util.CardUtil; +import java.util.List; import java.util.UUID; /** @@ -29,21 +31,28 @@ protected AddCardSubTypeTargetEffect(final AddCardSubTypeTargetEffect effect) { } @Override - public boolean apply(Game game, Ability source) { - boolean result = false; + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; + permanent.addSubType(game, addedSubType); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { for (UUID targetId : getTargetPointer().getTargets(game, source)) { Permanent target = game.getPermanent(targetId); if (target != null) { - target.addSubType(game, addedSubType); - result = true; + affectedObjects.add(target); } } - if (!result) { - if (this.getDuration() == Duration.Custom) { + if (affectedObjects.isEmpty()) { + if (duration == Duration.Custom) { this.discard(); } + return false; } - return result; + return true; } @Override diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardSubtypeAllEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardSubtypeAllEffect.java index 526075f937af..dc859a3da43d 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardSubtypeAllEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardSubtypeAllEffect.java @@ -1,5 +1,6 @@ package mage.abilities.effects.common.continuous; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffectImpl; import mage.constants.*; @@ -7,6 +8,8 @@ import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.List; + /** * @author Galatolol */ @@ -33,13 +36,19 @@ protected AddCardSubtypeAllEffect(final AddCardSubtypeAllEffect effect) { } @Override - public boolean apply(Game game, Ability source) { - for (Permanent perm : game.getBattlefield().getActivePermanents( - filter, source.getControllerId(), source, game - )) { - perm.addSubType(game, addedSubtype); + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; + permanent.addSubType(game, addedSubtype); } - return true; + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + affectedObjects.addAll(game.getBattlefield().getActivePermanents( + filter, source.getControllerId(), source, game + )); + return !affectedObjects.isEmpty(); } @Override diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardSubtypeAttachedEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardSubtypeAttachedEffect.java index d1b489acc284..d830890fce9e 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardSubtypeAttachedEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardSubtypeAttachedEffect.java @@ -1,5 +1,6 @@ package mage.abilities.effects.common.continuous; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffectImpl; import mage.constants.*; @@ -7,6 +8,8 @@ import mage.game.permanent.Permanent; import mage.util.CardUtil; +import java.util.List; + /** * @author nantuko */ @@ -26,14 +29,23 @@ protected AddCardSubtypeAttachedEffect(final AddCardSubtypeAttachedEffect effect } @Override - public boolean apply(Game game, Ability source) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + ((Permanent) object).addSubType(game, addedSubtype); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Permanent equipment = game.getPermanent(source.getSourceId()); if (equipment != null && equipment.getAttachedTo() != null) { Permanent target = game.getPermanent(equipment.getAttachedTo()); - if (target != null) - target.addSubType(game, addedSubtype); + if (target != null) { + affectedObjects.add(target); + return true; + } } - return true; + return false; } @Override diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardSuperTypeAttachedEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardSuperTypeAttachedEffect.java index 2525b44a3c15..c57d2a8c3f7a 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardSuperTypeAttachedEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardSuperTypeAttachedEffect.java @@ -1,11 +1,13 @@ package mage.abilities.effects.common.continuous; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffectImpl; import mage.constants.*; import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.List; import java.util.Locale; /** @@ -30,15 +32,22 @@ protected AddCardSuperTypeAttachedEffect(final AddCardSuperTypeAttachedEffect ef } @Override - public boolean apply(Game game, Ability source) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + ((Permanent) object).addSuperType(game, addedSuperType); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Permanent equipment = game.getPermanent(source.getSourceId()); if (equipment != null && equipment.getAttachedTo() != null) { Permanent target = game.getPermanent(equipment.getAttachedTo()); if (target != null) { - target.addSuperType(game, addedSuperType); + affectedObjects.add(target); } } - return true; + return !affectedObjects.isEmpty(); } @Override diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardTypeAttachedEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardTypeAttachedEffect.java index fd5ec859c29e..8a50bdea7a71 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardTypeAttachedEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardTypeAttachedEffect.java @@ -1,6 +1,7 @@ package mage.abilities.effects.common.continuous; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffectImpl; import mage.constants.*; @@ -8,6 +9,8 @@ import mage.game.permanent.Permanent; import mage.util.CardUtil; +import java.util.List; + /** * @author nantuko */ @@ -31,6 +34,26 @@ protected AddCardTypeAttachedEffect(final AddCardTypeAttachedEffect effect) { this.attachmentType = effect.attachmentType; } + @Override + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + ((Permanent) object).addCardType(game, addedCardType); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + Permanent equipment = game.getPermanent(source.getSourceId()); + if (equipment != null && equipment.getAttachedTo() != null) { + Permanent target = game.getPermanent(equipment.getAttachedTo()); + if (target != null) { + affectedObjects.add(target); + } + } + return !affectedObjects.isEmpty(); + } + + @Override public boolean apply(Game game, Ability source) { Permanent equipment = game.getPermanent(source.getSourceId()); diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardTypeSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardTypeSourceEffect.java index 078e2b09e911..cd704db78109 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardTypeSourceEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardTypeSourceEffect.java @@ -1,5 +1,6 @@ package mage.abilities.effects.common.continuous; +import mage.MageItem; import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.Mode; @@ -7,11 +8,10 @@ import mage.constants.*; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.util.CardUtil; import java.util.ArrayList; import java.util.List; -import java.util.stream.Collectors; +import java.util.Locale; /** * @author emerald000 @@ -49,20 +49,34 @@ public void init(Ability source, Game game) { } @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent != null - && (affectedObjectList.contains(new MageObjectReference(permanent, game)) - // Workaround to support abilities like "As long as __, this permanent is a __ in addition to its other types." - || !duration.isOnlyValidIfNoZoneChange())) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { for (CardType cardType : addedCardTypes) { - permanent.addCardType(game, cardType); + ((Permanent) object).addCardType(game, cardType); } - return true; - } else if (this.getDuration() == Duration.Custom) { + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + Permanent permanent = null; + if (!duration.isOnlyValidIfNoZoneChange()) { + // Workaround to support abilities like "As long as __, this permanent is a __ in addition to its other types." + permanent = game.getPermanent(source.getSourceId()); + } else { + for (MageObjectReference mor : affectedObjectList) { + permanent = mor.getPermanent(game); + if (permanent != null) { + break; + } + } + } + if (permanent == null) { this.discard(); + return false; } - return false; + affectedObjects.add(permanent); + return true; } @Override @@ -77,20 +91,19 @@ public String getText(Mode mode) { } StringBuilder sb = new StringBuilder(); sb.append("{this} becomes "); - sb.append(CardUtil.addArticle( - addedCardTypes - .stream() - .map(CardType::toString) - .map(String::toLowerCase) - .collect(Collectors.joining(" ")) - )); - if (!addedCardTypes.contains(CardType.ARTIFACT) || !addedCardTypes.contains(CardType.CREATURE)) { - sb.append(" in addition to its other types"); - } - if (!this.getDuration().toString().isEmpty()) { - sb.append(' '); - sb.append(this.getDuration()); + boolean article = false; + for (CardType cardType : addedCardTypes) { + if (!article) { + if (cardType.toString().startsWith("A") || cardType.toString().startsWith("E")) { + sb.append("an "); + } else { + sb.append("a "); + } + article = true; + } + sb.append(cardType.toString().toLowerCase(Locale.ENGLISH)).append(" "); } + sb.append("in addition to its other types ").append(this.getDuration().toString()); return sb.toString(); } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/AddChosenSubtypeEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddChosenSubtypeEffect.java index e37f1145dab2..06e678f8f69c 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/AddChosenSubtypeEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddChosenSubtypeEffect.java @@ -1,5 +1,6 @@ package mage.abilities.effects.common.continuous; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.common.ChooseCreatureTypeEffect; @@ -7,6 +8,8 @@ import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.List; + public class AddChosenSubtypeEffect extends ContinuousEffectImpl { public AddChosenSubtypeEffect() { @@ -19,15 +22,24 @@ protected AddChosenSubtypeEffect(final AddChosenSubtypeEffect effect) { } @Override - public boolean apply(Game game, Ability source) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; + SubType subType = ChooseCreatureTypeEffect.getChosenCreatureType(permanent.getId(), game); + permanent.addSubType(game, subType); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Permanent permanent = game.getPermanent(source.getSourceId()); if (permanent != null) { SubType subType = ChooseCreatureTypeEffect.getChosenCreatureType(permanent.getId(), game); if (subType != null) { - permanent.addSubType(game, subType); + affectedObjects.add(permanent); } } - return true; + return !affectedObjects.isEmpty(); } @Override diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCreatureSubTypeAllMultiZoneEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCreatureSubTypeAllMultiZoneEffect.java index 8367e9ceab7a..e6768ba08cb0 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCreatureSubTypeAllMultiZoneEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCreatureSubTypeAllMultiZoneEffect.java @@ -1,11 +1,14 @@ package mage.abilities.effects.common.continuous; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.common.ChooseCreatureTypeEffect; import mage.cards.Card; import mage.constants.*; -import mage.filter.common.*; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.common.FilterControlledCreatureSpell; +import mage.filter.common.FilterOwnedCreatureCard; import mage.game.Game; import mage.game.command.CommandObject; import mage.game.command.Commander; @@ -71,7 +74,7 @@ public AddCreatureSubTypeAllMultiZoneEffect copy() { } @Override - public boolean apply(Game game, Ability source) { + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { UUID controllerId = source.getControllerId(); Player controller = game.getPlayer(controllerId); SubType subType = this.chosenType; @@ -81,32 +84,31 @@ public boolean apply(Game game, Ability source) { if (controller == null || subType == null) { return false; } - // creatures cards you own that aren't on the battlefield // in graveyard for (UUID cardId : controller.getGraveyard()) { Card card = game.getCard(cardId); if (filterCard.match(card, controllerId, source, game) && !card.hasSubtype(subType, game)) { - game.getState().getCreateMageObjectAttribute(card, game).getSubtype().add(subType); + affectedObjects.add(card); } } // on Hand for (UUID cardId : controller.getHand()) { Card card = game.getCard(cardId); if (filterCard.match(card, controllerId, source, game) && !card.hasSubtype(subType, game)) { - game.getState().getCreateMageObjectAttribute(card, game).getSubtype().add(subType); + affectedObjects.add(card); } } // in Exile for (Card card : game.getState().getExile().getAllCards(game, controllerId)) { if (filterCard.match(card, controllerId, source, game) && !card.hasSubtype(subType, game)) { - game.getState().getCreateMageObjectAttribute(card, game).getSubtype().add(subType); + affectedObjects.add(card); } } // in Library (e.g. for Mystical Teachings) for (Card card : controller.getLibrary().getCards(game)) { if (filterCard.match(card, controllerId, source, game) && !card.hasSubtype(subType, game)) { - game.getState().getCreateMageObjectAttribute(card, game).getSubtype().add(subType); + affectedObjects.add(card); } } // commander in command zone @@ -114,7 +116,7 @@ public boolean apply(Game game, Ability source) { if (commandObject instanceof Commander) { Card card = game.getCard((commandObject).getId()); if (filterCard.match(card, controllerId, source, game) && !card.hasSubtype(subType, game)) { - game.getState().getCreateMageObjectAttribute(card, game).getSubtype().add(subType); + affectedObjects.add(card); } } } @@ -125,7 +127,7 @@ public boolean apply(Game game, Ability source) { && filterSpell.match(stackObject, controllerId, source, game) && !stackObject.hasSubtype(subType, game)) { Card card = ((Spell) stackObject).getCard(); - game.getState().getCreateMageObjectAttribute(card, game).getSubtype().add(subType); + affectedObjects.add(card); } } // creatures you control @@ -133,9 +135,26 @@ public boolean apply(Game game, Ability source) { filterPermanent, controllerId, game); for (Permanent creature : creatures) { if (creature != null) { - creature.addSubType(game, subType); + affectedObjects.add(creature); + } + } + return !affectedObjects.isEmpty(); + } + + @Override + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + SubType subType = this.chosenType; + if (subType == null) { + subType = ChooseCreatureTypeEffect.getChosenCreatureType(source.getSourceId(), game); + } + for (MageItem object : affectedObjects) { + if (object instanceof Permanent) { + Permanent permanent = (Permanent) object; + permanent.addSubType(game, subType); + } else if (object instanceof Card) { + Card card = (Card) object; + game.getState().getCreateMageObjectAttribute(card, game).getSubtype().add(subType); } } - return true; } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCreatureTypeAdditionEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCreatureTypeAdditionEffect.java index b5dbdd6f9808..620b948f7078 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCreatureTypeAdditionEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCreatureTypeAdditionEffect.java @@ -1,11 +1,15 @@ package mage.abilities.effects.common.continuous; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffectImpl; import mage.constants.*; import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.ArrayList; +import java.util.List; + /** * @author JRHerlehy Created on 4/8/17. */ @@ -41,7 +45,7 @@ public boolean hasLayer(Layer layer) { } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Permanent creature; if (source.getTargets().getFirstTarget() == null) { creature = game.getPermanent(getTargetPointer().getFirst(game, source)); @@ -51,25 +55,37 @@ public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) creature = game.getPermanentEntering(source.getTargets().getFirstTarget()); } } - if (creature == null) { - this.used = true; - return false; + if (creature != null) { + affectedObjects.add(creature); } - switch (layer) { - case TypeChangingEffects_4: - creature.addSubType(game, subType); - break; - case ColorChangingEffects_5: - if (this.giveBlackColor) { - creature.getColor(game).setBlack(true); - } - break; + return !affectedObjects.isEmpty(); + } + + @Override + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent creature = (Permanent) object; + switch (layer) { + case TypeChangingEffects_4: + creature.addSubType(game, subType); + break; + case ColorChangingEffects_5: + if (this.giveBlackColor) { + creature.getColor(game).setBlack(true); + } + break; + } } - return true; } @Override - public boolean apply(Game game, Ability source) { + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + List affectedObjects = new ArrayList<>(); + if (queryAffectedObjects(layer, source, game, affectedObjects)) { + applyToObjects(layer, sublayer, source, game, affectedObjects); + return true; + } + this.used = true; return false; } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesAllBasicsControlledEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesAllBasicsControlledEffect.java index b5991f27b3a7..b0686b0315c1 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesAllBasicsControlledEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesAllBasicsControlledEffect.java @@ -1,5 +1,6 @@ package mage.abilities.effects.common.continuous; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.mana.*; @@ -8,7 +9,6 @@ import mage.game.Game; import mage.game.permanent.Permanent; -import java.util.ArrayList; import java.util.List; /** @@ -44,9 +44,16 @@ public BecomesAllBasicsControlledEffect copy() { } @Override - public boolean apply(Game game, Ability source) { - for (Permanent permanent : game.getBattlefield().getActivePermanents( - StaticFilters.FILTER_CONTROLLED_PERMANENT_LAND, source.getControllerId(), game)) { + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + affectedObjects.addAll(game.getBattlefield().getActivePermanents( + StaticFilters.FILTER_CONTROLLED_PERMANENT_LAND, source.getControllerId(), game)); + return !affectedObjects.isEmpty(); + } + + @Override + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; permanent.addSubType(game, SubType.PLAINS, SubType.ISLAND, @@ -67,6 +74,5 @@ public boolean apply(Game game, Ability source) { permanent.addAbility(ability, source.getSourceId(), game); } } - return true; } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesAuraSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesAuraSourceEffect.java index 03b4e74d9f27..36fb0b7d8f98 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesAuraSourceEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesAuraSourceEffect.java @@ -1,6 +1,7 @@ package mage.abilities.effects.common.continuous; +import mage.MageItem; import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffectImpl; @@ -10,6 +11,9 @@ import mage.game.permanent.Permanent; import mage.target.Target; +import java.util.ArrayList; +import java.util.List; + /** * @author LevelX2 */ @@ -46,30 +50,40 @@ public void init(Ability source, Game game) { } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - Permanent permanent = affectedObjectList.get(0).getPermanent(game); - if (permanent != null) { + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + for (MageObjectReference mor : affectedObjectList) { + Permanent permanent = mor.getPermanent(game); + if (permanent != null) { + affectedObjects.add(permanent); + } + } + return !affectedObjects.isEmpty(); + } + + @Override + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; switch (layer) { case TypeChangingEffects_4: - if (sublayer == SubLayer.NA) { - permanent.addSubType(game, SubType.AURA); - } + permanent.addSubType(game, SubType.AURA); break; case AbilityAddingRemovingEffects_6: - if (sublayer == SubLayer.NA) { - permanent.addAbility(newAbility, source.getSourceId(), game); - permanent.getSpellAbility().getTargets().clear(); - permanent.getSpellAbility().getTargets().add(target); - } + permanent.addAbility(newAbility, source.getSourceId(), game); + permanent.getSpellAbility().getTargets().clear(); + permanent.getSpellAbility().getTargets().add(target); } - return true; } - this.discard(); - return false; } @Override - public boolean apply(Game game, Ability source) { + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + List affectedObjects = new ArrayList<>(); + if (queryAffectedObjects(layer, source, game, affectedObjects)) { + applyToObjects(layer, sublayer, source, game, affectedObjects); + return true; + } + this.discard(); return false; } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesBasicLandEnchantedEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesBasicLandEnchantedEffect.java index 9ae5efffe3b5..9bd9d9120d0d 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesBasicLandEnchantedEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesBasicLandEnchantedEffect.java @@ -1,5 +1,6 @@ package mage.abilities.effects.common.continuous; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.mana.*; @@ -8,9 +9,7 @@ import mage.game.permanent.Permanent; import mage.util.CardUtil; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; +import java.util.*; import java.util.stream.Collectors; public class BecomesBasicLandEnchantedEffect extends ContinuousEffectImpl { @@ -38,48 +37,54 @@ public BecomesBasicLandEnchantedEffect copy() { } @Override - public boolean apply(Game game, Ability source) { - Permanent enchantment = game.getPermanent(source.getSourceId()); - if (enchantment == null || enchantment.getAttachedTo() == null) { - return false; - } - Permanent permanent = game.getPermanent(enchantment.getAttachedTo()); - if (permanent == null) { - return false; + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + Permanent attachment = game.getPermanent(source.getSourceId()); + if (attachment != null && attachment.getAttachedTo() != null) { + Permanent permanent = game.getPermanent(attachment.getAttachedTo()); + if (permanent != null) { + affectedObjects.add(permanent); + } } - // lands intrictically have the mana ability associated with their type, so added here in layer 4 - permanent.removeAllSubTypes(game, SubTypeSet.NonBasicLandType); - permanent.addSubType(game, landTypes); - permanent.removeAllAbilities(source.getSourceId(), game); - for (SubType landType : landTypes) { - switch (landType) { - case PLAINS: - if (permanent.hasSubtype(SubType.PLAINS, game)) { - permanent.addAbility(new WhiteManaAbility(), source.getSourceId(), game); - } - break; - case ISLAND: - if (permanent.hasSubtype(SubType.ISLAND, game)) { - permanent.addAbility(new BlueManaAbility(), source.getSourceId(), game); - } - break; - case SWAMP: - if (permanent.hasSubtype(SubType.SWAMP, game)) { - permanent.addAbility(new BlackManaAbility(), source.getSourceId(), game); - } - break; - case MOUNTAIN: - if (permanent.hasSubtype(SubType.MOUNTAIN, game)) { - permanent.addAbility(new RedManaAbility(), source.getSourceId(), game); - } - break; - case FOREST: - if (permanent.hasSubtype(SubType.FOREST, game)) { - permanent.addAbility(new GreenManaAbility(), source.getSourceId(), game); - } - break; + return !affectedObjects.isEmpty(); + } + + @Override + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; + // lands intrictically have the mana ability associated with their type, so added here in layer 4 + permanent.removeAllSubTypes(game, SubTypeSet.NonBasicLandType); + permanent.addSubType(game, landTypes); + permanent.removeAllAbilities(source.getSourceId(), game); + for (SubType landType : landTypes) { + switch (landType) { + case PLAINS: + if (permanent.hasSubtype(SubType.PLAINS, game)) { + permanent.addAbility(new WhiteManaAbility(), source.getSourceId(), game); + } + break; + case ISLAND: + if (permanent.hasSubtype(SubType.ISLAND, game)) { + permanent.addAbility(new BlueManaAbility(), source.getSourceId(), game); + } + break; + case SWAMP: + if (permanent.hasSubtype(SubType.SWAMP, game)) { + permanent.addAbility(new BlackManaAbility(), source.getSourceId(), game); + } + break; + case MOUNTAIN: + if (permanent.hasSubtype(SubType.MOUNTAIN, game)) { + permanent.addAbility(new RedManaAbility(), source.getSourceId(), game); + } + break; + case FOREST: + if (permanent.hasSubtype(SubType.FOREST, game)) { + permanent.addAbility(new GreenManaAbility(), source.getSourceId(), game); + } + break; + } } } - return true; } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesBasicLandTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesBasicLandTargetEffect.java index fde7e556c32f..d8b4f7e8b3e9 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesBasicLandTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesBasicLandTargetEffect.java @@ -1,5 +1,6 @@ package mage.abilities.effects.common.continuous; +import mage.MageItem; import mage.abilities.Abilities; import mage.abilities.Ability; import mage.abilities.Mode; @@ -13,10 +14,7 @@ import mage.players.Player; import mage.util.CardUtil; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.UUID; +import java.util.*; import java.util.stream.Collectors; /** @@ -96,58 +94,65 @@ protected void chooseLandType(Ability source, Game game) { } @Override - public boolean apply(Game game, Ability source) { - for (UUID targetPermanent : getTargetPointer().getTargets(game, source)) { - Permanent land = game.getPermanent(targetPermanent); - if (land == null) { - continue; + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + for (UUID targetId : getTargetPointer().getTargets(game, source)) { + Permanent permanent = game.getPermanent(targetId); + if (permanent != null) { + affectedObjects.add(permanent); } - if (!land.isLand(game)) { - land.addCardType(game, CardType.LAND); + } + return !affectedObjects.isEmpty(); + } + + @Override + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; + if (!permanent.isLand(game)) { + permanent.addCardType(game, CardType.LAND); } if (loseOther) { // 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); + permanent.removeAllAbilities(source.getSourceId(), game); // 305.7 - land.removeAllSubTypes(game, SubTypeSet.NonBasicLandType); + permanent.removeAllSubTypes(game, SubTypeSet.NonBasicLandType); } - land.addSubType(game, landTypes); + permanent.addSubType(game, landTypes); // add intrinsic land abilities here not in layer 6 - Abilities landAbilities = land.getAbilities(game); + Abilities landAbilities = permanent.getAbilities(game); for (SubType landType : landTypes) { switch (landType) { case PLAINS: if (!landAbilities.containsClass(WhiteManaAbility.class)) { - land.addAbility(new WhiteManaAbility(), source.getSourceId(), game); + permanent.addAbility(new WhiteManaAbility(), source.getSourceId(), game); } break; case ISLAND: if (!landAbilities.containsClass(BlueManaAbility.class)) { - land.addAbility(new BlueManaAbility(), source.getSourceId(), game); + permanent.addAbility(new BlueManaAbility(), source.getSourceId(), game); } break; case SWAMP: if (!landAbilities.containsClass(BlackManaAbility.class)) { - land.addAbility(new BlackManaAbility(), source.getSourceId(), game); + permanent.addAbility(new BlackManaAbility(), source.getSourceId(), game); } break; case MOUNTAIN: if (!landAbilities.containsClass(RedManaAbility.class)) { - land.addAbility(new RedManaAbility(), source.getSourceId(), game); + permanent.addAbility(new RedManaAbility(), source.getSourceId(), game); } break; case FOREST: if (!landAbilities.containsClass(GreenManaAbility.class)) { - land.addAbility(new GreenManaAbility(), source.getSourceId(), game); + permanent.addAbility(new GreenManaAbility(), source.getSourceId(), game); } break; } } } - return true; } @Override diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesColorSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesColorSourceEffect.java index 43c636b97098..e30d271ae743 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesColorSourceEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesColorSourceEffect.java @@ -1,5 +1,6 @@ package mage.abilities.effects.common.continuous; +import mage.MageItem; import mage.MageObject; import mage.ObjectColor; import mage.abilities.Ability; @@ -13,6 +14,8 @@ import mage.game.Game; import mage.players.Player; +import java.util.List; + /** * @author LoneFox */ @@ -62,21 +65,21 @@ public void init(Ability source, Game game) { } @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller == null) { - return false; + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + MageObject mageObject = game.getObject(source.getSourceId()); + if (mageObject != null) { + affectedObjects.add(mageObject); + } else { + this.discard(); } - if (setColor != null) { - MageObject sourceObject = game.getObject(source); - if (sourceObject != null) { - sourceObject.getColor(game).setColor(setColor); - } else { - this.discard(); - } - return true; + return !affectedObjects.isEmpty(); + } + + @Override + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + ((MageObject) object).getColor(game).setColor(setColor); } - return false; } @Override diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesColorTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesColorTargetEffect.java index 6f2ae65c00a4..a8a201e08b7b 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesColorTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesColorTargetEffect.java @@ -1,7 +1,6 @@ package mage.abilities.effects.common.continuous; -import java.util.UUID; - +import mage.MageItem; import mage.MageObject; import mage.ObjectColor; import mage.abilities.Ability; @@ -17,6 +16,9 @@ import mage.game.stack.Spell; import mage.players.Player; +import java.util.List; +import java.util.UUID; + /** * @author LevelX */ @@ -71,34 +73,31 @@ public void init(Ability source, Game game) { } @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller == null) { - return false; + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + for (UUID targetId : getTargetPointer().getTargets(game, source)) { + MageObject mageObject = game.getObject(targetId); + if (mageObject instanceof Spell || mageObject instanceof Permanent) { + affectedObjects.add(mageObject); + } } - if (setColor != null) { - boolean objectFound = false; - for (UUID targetId : getTargetPointer().getTargets(game, source)) { - MageObject targetObject = game.getObject(targetId); - if (targetObject != null) { - if (targetObject instanceof Spell || targetObject instanceof Permanent) { - objectFound = true; - if (retainColor) { - targetObject.getColor(game).addColor(setColor); - } else { - targetObject.getColor(game).setColor(setColor); - } - } else { - objectFound = false; - } - } + if (affectedObjects.isEmpty()) { + if (duration == Duration.Custom) { + discard(); } - if (!objectFound && this.getDuration() == Duration.Custom) { - this.discard(); + return false; + } + return true; + } + + @Override + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + MageObject mageObject = (MageObject) object; + if (retainColor) { + mageObject.getColor(game).addColor(setColor); + } else { + mageObject.getColor(game).setColor(setColor); } - return true; - } else { - throw new UnsupportedOperationException("No color set"); } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureAllEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureAllEffect.java index 8949242460cd..3556e542dbdf 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureAllEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureAllEffect.java @@ -1,5 +1,6 @@ package mage.abilities.effects.common.continuous; +import mage.MageItem; import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.Mode; @@ -10,8 +11,8 @@ import mage.game.permanent.Permanent; import mage.game.permanent.token.Token; -import java.util.HashSet; -import java.util.Set; +import java.util.ArrayList; +import java.util.List; /** * @author LevelX2 @@ -70,21 +71,24 @@ public BecomesCreatureAllEffect copy() { } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - Set affectedPermanents = new HashSet<>(); + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { if (getAffectedObjectsSet()) { - for (MageObjectReference ref : affectedObjectList) { - affectedPermanents.add(ref.getPermanent(game)); + for (MageObjectReference mor : affectedObjectList) { + Permanent permanent = mor.getPermanent(game); + if (permanent != null) { + affectedObjects.add(permanent); + } } } else { - affectedPermanents = new HashSet<>(game.getBattlefield() - .getActivePermanents(filter, source.getControllerId(), source, game)); + affectedObjects.addAll(game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game)); } + return !affectedObjects.isEmpty(); + } - for (Permanent permanent : affectedPermanents) { - if (permanent == null) { - continue; - } + @Override + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; switch (layer) { case TextChangingEffects_3: if (loseName) { @@ -140,14 +144,17 @@ public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) break; } } - return true; } @Override - public boolean apply(Game game, Ability source) { + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + List affectedObjects = new ArrayList<>(); + if (queryAffectedObjects(layer, source, game, affectedObjects)) { + applyToObjects(layer, sublayer, source, game, affectedObjects); + return true; + } return false; } - @Override public boolean hasLayer(Layer layer) { return layer == Layer.PTChangingEffects_7 diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureAttachedEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureAttachedEffect.java index 11844e6c3228..0b7f16a7e3d6 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureAttachedEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureAttachedEffect.java @@ -1,5 +1,6 @@ package mage.abilities.effects.common.continuous; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffectImpl; import mage.constants.*; @@ -7,6 +8,9 @@ import mage.game.permanent.Permanent; import mage.game.permanent.token.Token; +import java.util.ArrayList; +import java.util.List; + /** * @author jeffwadsworth */ @@ -52,83 +56,94 @@ public BecomesCreatureAttachedEffect copy() { } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - Permanent enchantment = game.getPermanent(source.getSourceId()); - if (enchantment == null) { - return false; + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + Permanent attachment = game.getPermanent(source.getSourceId()); + if (attachment != null && attachment.getAttachedTo() != null) { + Permanent attachedTo = game.getPermanent(attachment.getAttachedTo()); + if (attachedTo != null) { + affectedObjects.add(attachedTo); + } } - Permanent permanent = game.getPermanent(enchantment.getAttachedTo()); - if (permanent == null) { - return true; - } - switch (layer) { - case TypeChangingEffects_4: - for (SuperType t : token.getSuperType(game)) { - permanent.addSuperType(game, t); - } - // card type - switch (loseType) { - case ALL: - case ALL_BUT_COLOR: - permanent.removeAllCardTypes(game); - break; - } - for (CardType t : token.getCardType(game)) { - permanent.addCardType(game, t); - } - - // sub type - switch (loseType) { - case ALL: - case ALL_BUT_COLOR: - permanent.removeAllSubTypes(game); - break; - case ABILITIES_SUBTYPE: - permanent.removeAllCreatureTypes(game); - break; - } - permanent.copySubTypesFrom(game, token); - break; - - case ColorChangingEffects_5: - if (loseType == LoseType.ALL || loseType == LoseType.COLOR) { - permanent.getColor(game).setWhite(false); - permanent.getColor(game).setBlue(false); - permanent.getColor(game).setBlack(false); - permanent.getColor(game).setRed(false); - permanent.getColor(game).setGreen(false); - } - if (token.getColor(game).hasColor()) { - permanent.getColor(game).addColor(token.getColor(game)); - } - break; - - case AbilityAddingRemovingEffects_6: - switch (loseType) { - case ALL: - case ALL_BUT_COLOR: - case ABILITIES: - case ABILITIES_SUBTYPE: - permanent.removeAllAbilities(source.getSourceId(), game); - break; - } - for (Ability ability : token.getAbilities()) { - permanent.addAbility(ability, source.getSourceId(), game, true); - } - break; - - case PTChangingEffects_7: - if (sublayer == SubLayer.SetPT_7b) { - permanent.getPower().setModifiedBaseValue(token.getPower().getValue()); - permanent.getToughness().setModifiedBaseValue(token.getToughness().getValue()); - } - break; + return !affectedObjects.isEmpty(); + } + + @Override + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; + switch (layer) { + case TypeChangingEffects_4: + for (SuperType t : token.getSuperType(game)) { + permanent.addSuperType(game, t); + } + // card type + switch (loseType) { + case ALL: + case ALL_BUT_COLOR: + permanent.removeAllCardTypes(game); + break; + } + for (CardType t : token.getCardType(game)) { + permanent.addCardType(game, t); + } + + // sub type + switch (loseType) { + case ALL: + case ALL_BUT_COLOR: + permanent.removeAllSubTypes(game); + break; + case ABILITIES_SUBTYPE: + permanent.removeAllCreatureTypes(game); + break; + } + permanent.copySubTypesFrom(game, token); + break; + + case ColorChangingEffects_5: + if (loseType == LoseType.ALL || loseType == LoseType.COLOR) { + permanent.getColor(game).setWhite(false); + permanent.getColor(game).setBlue(false); + permanent.getColor(game).setBlack(false); + permanent.getColor(game).setRed(false); + permanent.getColor(game).setGreen(false); + } + if (token.getColor(game).hasColor()) { + permanent.getColor(game).addColor(token.getColor(game)); + } + break; + + case AbilityAddingRemovingEffects_6: + switch (loseType) { + case ALL: + case ALL_BUT_COLOR: + case ABILITIES: + case ABILITIES_SUBTYPE: + permanent.removeAllAbilities(source.getSourceId(), game); + break; + } + for (Ability ability : token.getAbilities()) { + permanent.addAbility(ability, source.getSourceId(), game, true); + } + break; + + case PTChangingEffects_7: + if (sublayer == SubLayer.SetPT_7b) { + permanent.getPower().setModifiedBaseValue(token.getPower().getValue()); + permanent.getToughness().setModifiedBaseValue(token.getToughness().getValue()); + } + break; + } } - return true; } @Override - public boolean apply(Game game, Ability source) { + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + List affectedObjects = new ArrayList<>(); + if (queryAffectedObjects(layer, source, game, affectedObjects)) { + applyToObjects(layer, sublayer, source, game, affectedObjects); + return true; + } return false; } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureIfVehicleEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureIfVehicleEffect.java index f04894de77c2..f5733a23c316 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureIfVehicleEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureIfVehicleEffect.java @@ -1,17 +1,20 @@ package mage.abilities.effects.common.continuous; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffectImpl; import mage.constants.*; import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.List; + /** * Created by IGOUDT on 5-4-2017. */ public class BecomesCreatureIfVehicleEffect extends ContinuousEffectImpl { - private CardType addedType = CardType.CREATURE; + private final CardType addedType = CardType.CREATURE; public BecomesCreatureIfVehicleEffect() { super(Duration.WhileOnBattlefield, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Benefit); @@ -24,16 +27,22 @@ protected BecomesCreatureIfVehicleEffect(final BecomesCreatureIfVehicleEffect ef } @Override - public boolean apply(Game game, Ability source) { - Permanent aura = game.getPermanent(source.getSourceId()); - if (aura != null && aura.getAttachedTo() != null) { - Permanent enchanted = game.getPermanent(aura.getAttachedTo()); - if (enchanted != null && enchanted.hasSubtype(SubType.VEHICLE, game)) { - enchanted.addCardType(game, addedType); + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + Permanent attachment = game.getPermanent(source.getSourceId()); + if (attachment != null && attachment.getAttachedTo() != null) { + Permanent attachedTo = game.getPermanent(attachment.getAttachedTo()); + if (attachedTo != null) { + affectedObjects.add(attachedTo); } } + return !affectedObjects.isEmpty(); + } - return true; + @Override + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + ((Permanent) object).addCardType(game, addedType); + } } @Override diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureSourceEffect.java index 7f3ef03a30ff..317974ddf30e 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureSourceEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureSourceEffect.java @@ -1,5 +1,6 @@ package mage.abilities.effects.common.continuous; +import mage.MageItem; import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.dynamicvalue.DynamicValue; @@ -9,6 +10,9 @@ import mage.game.permanent.Permanent; import mage.game.permanent.token.Token; +import java.util.ArrayList; +import java.util.List; + /** * @author BetaSteward_at_googlemail.com, xenohedron */ @@ -89,76 +93,91 @@ public void init(Ability source, Game game) { } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - Permanent permanent; + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { if (getAffectedObjectsSet()) { - permanent = affectedObjectList.get(0).getPermanent(game); + for (MageObjectReference mor : affectedObjectList) { + Permanent permanent = mor.getPermanent(game); + if (permanent != null) { + affectedObjects.add(permanent); + } + } } else { - permanent = game.getPermanent(source.getSourceId()); - } - if (permanent == null) { - if (duration == Duration.Custom) { - this.discard(); + Permanent permanent = game.getPermanent(source.getSourceId()); + if (permanent != null) { + affectedObjects.add(permanent); } - return false; } - switch (layer) { - case TypeChangingEffects_4: - if (retainType == null) { - permanent.removeAllCardTypes(game); - permanent.removeAllSubTypes(game); - } - for (SuperType superType : token.getSuperType(game)) { - permanent.addSuperType(game, superType); - } - for (CardType cardType : token.getCardType(game)) { - permanent.addCardType(game, cardType); - } - if (loseEquipmentType) { - permanent.removeSubType(game, SubType.EQUIPMENT); - } - if (!keepCreatureSubtypes) { - permanent.removeAllCreatureTypes(game); - } - permanent.copySubTypesFrom(game, token); - break; + return !affectedObjects.isEmpty(); + } - case ColorChangingEffects_5: - if (token.getColor(game).hasColor()) { - permanent.getColor(game).setColor(token.getColor(game)); - } - break; + @Override + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; + switch (layer) { + case TypeChangingEffects_4: + if (retainType == null) { + permanent.removeAllCardTypes(game); + permanent.removeAllSubTypes(game); + } + for (SuperType superType : token.getSuperType(game)) { + permanent.addSuperType(game, superType); + } + for (CardType cardType : token.getCardType(game)) { + permanent.addCardType(game, cardType); + } + if (loseEquipmentType) { + permanent.removeSubType(game, SubType.EQUIPMENT); + } + if (!keepCreatureSubtypes) { + permanent.removeAllCreatureTypes(game); + } + permanent.copySubTypesFrom(game, token); + break; - case AbilityAddingRemovingEffects_6: - if (loseAbilities) { - permanent.removeAllAbilities(source.getSourceId(), game); - } - for (Ability ability : token.getAbilities()) { - permanent.addAbility(ability, source.getSourceId(), game, true); - } - break; - - case PTChangingEffects_7: - if (sublayer == SubLayer.SetPT_7b) { - if (power != null) { - permanent.getPower().setModifiedBaseValue(power.calculate(game, source, this)); // check all other becomes to use calculate? - } else if (token.getPower() != null) { - permanent.getPower().setModifiedBaseValue(token.getPower().getValue()); + case ColorChangingEffects_5: + if (token.getColor(game).hasColor()) { + permanent.getColor(game).setColor(token.getColor(game)); } - if (toughness != null) { - permanent.getToughness().setModifiedBaseValue(toughness.calculate(game, source, this)); - } else if (token.getToughness() != null) { - permanent.getToughness().setModifiedBaseValue(token.getToughness().getValue()); + break; + + case AbilityAddingRemovingEffects_6: + if (loseAbilities) { + permanent.removeAllAbilities(source.getSourceId(), game); } - } - break; - } + for (Ability ability : token.getAbilities()) { + permanent.addAbility(ability, source.getSourceId(), game, true); + } + break; - return true; + case PTChangingEffects_7: + if (sublayer == SubLayer.SetPT_7b) { + if (power != null) { + permanent.getPower().setModifiedBaseValue(power.calculate(game, source, this)); // check all other becomes to use calculate? + } else if (token.getPower() != null) { + permanent.getPower().setModifiedBaseValue(token.getPower().getValue()); + } + if (toughness != null) { + permanent.getToughness().setModifiedBaseValue(toughness.calculate(game, source, this)); + } else if (token.getToughness() != null) { + permanent.getToughness().setModifiedBaseValue(token.getToughness().getValue()); + } + } + break; + } + } } @Override - public boolean apply(Game game, Ability source) { + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + List affectedObjects = new ArrayList<>(); + if (queryAffectedObjects(layer, source, game, affectedObjects)) { + applyToObjects(layer, sublayer, source, game, affectedObjects); + return true; + } + if (duration == Duration.Custom) { + this.discard(); + } return false; } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureTargetEffect.java index 4b4a8e3f3622..c0cc6c951b14 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureTargetEffect.java @@ -1,5 +1,6 @@ package mage.abilities.effects.common.continuous; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.Mode; import mage.abilities.effects.ContinuousEffectImpl; @@ -8,6 +9,8 @@ import mage.game.permanent.Permanent; import mage.game.permanent.token.Token; +import java.util.ArrayList; +import java.util.List; import java.util.UUID; /** @@ -78,13 +81,20 @@ public BecomesCreatureTargetEffect copy() { } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - boolean result = false; - for (UUID permanentId : getTargetPointer().getTargets(game, source)) { - Permanent permanent = game.getPermanent(permanentId); - if (permanent == null) { - continue; + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + for (UUID targetId : getTargetPointer().getTargets(game, source)) { + Permanent permanent = game.getPermanent(targetId); + if (permanent != null) { + affectedObjects.add(permanent); } + } + return !affectedObjects.isEmpty(); + } + + @Override + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; switch (layer) { case TextChangingEffects_3: if (loseName) { @@ -145,12 +155,20 @@ public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) permanent.getPower().setModifiedBaseValue(token.getPower().getValue()); } } - result = true; } - if (!result && this.duration == Duration.Custom) { + } + + @Override + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + List affectedObjects = new ArrayList<>(); + if (queryAffectedObjects(layer, source, game, affectedObjects)) { + applyToObjects(layer, sublayer, source, game, affectedObjects); + return true; + } + if (duration == Duration.Custom) { this.discard(); } - return result; + return false; } public BecomesCreatureTargetEffect setRemoveSubtypes(boolean removeSubtypes) { @@ -158,11 +176,6 @@ public BecomesCreatureTargetEffect setRemoveSubtypes(boolean removeSubtypes) { return this; } - @Override - public boolean apply(Game game, Ability source) { - return false; - } - @Override public boolean hasLayer(Layer layer) { return layer == Layer.PTChangingEffects_7 diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureTypeTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureTypeTargetEffect.java index dd1109ebdc24..d3ce2d888354 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureTypeTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureTypeTargetEffect.java @@ -1,15 +1,13 @@ package mage.abilities.effects.common.continuous; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffectImpl; import mage.constants.*; import mage.game.Game; import mage.game.permanent.Permanent; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.UUID; +import java.util.*; /** * @author LevelX2 @@ -50,25 +48,29 @@ public BecomesCreatureTypeTargetEffect copy() { } @Override - public boolean apply(Game game, Ability source) { - boolean flag = false; - for (UUID targetPermanent : getTargetPointer().getTargets(game, source)) { - Permanent permanent = game.getPermanent(targetPermanent); - if (permanent == null) { - continue; + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + for (UUID targetId : getTargetPointer().getTargets(game, source)) { + Permanent permanent = game.getPermanent(targetId); + if (permanent != null) { + affectedObjects.add(permanent); } - flag = true; + } + if (affectedObjects.isEmpty() && duration == Duration.Custom) { + this.discard(); + return false; + } + return !affectedObjects.isEmpty(); + } + + @Override + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; if (loseOther) { permanent.removeAllCreatureTypes(game); } - for (SubType subtype : subtypes) { - permanent.addSubType(game, subtype); - } - } - if (!flag && duration == Duration.Custom) { - discard(); + permanent.addSubType(game, subtypes); } - return true; } private String setText() { diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesEnchantmentSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesEnchantmentSourceEffect.java index 755024a05557..46d039c28f01 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesEnchantmentSourceEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesEnchantmentSourceEffect.java @@ -1,5 +1,6 @@ package mage.abilities.effects.common.continuous; +import mage.MageItem; import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffectImpl; @@ -7,6 +8,8 @@ import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.List; + /** * @author jeffwadsworth */ @@ -34,15 +37,27 @@ public void init(Ability source, Game game) { } @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = affectedObjectList.get(0).getPermanent(game); - if (permanent == null) { + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + for (MageObjectReference mor : affectedObjectList) { + Permanent permanent = mor.getPermanent(game); + if (permanent != null) { + affectedObjects.add(permanent); + } + } + if (affectedObjects.isEmpty()) { this.discard(); return false; } - permanent.removeAllCardTypes(game); - permanent.addCardType(game, CardType.ENCHANTMENT); - permanent.retainAllEnchantmentSubTypes(game); return true; } + + @Override + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; + permanent.removeAllCardTypes(game); + permanent.addCardType(game, CardType.ENCHANTMENT); + permanent.retainAllEnchantmentSubTypes(game); + } + } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesFaceDownCreatureAllEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesFaceDownCreatureAllEffect.java index 73a24776138a..87ff787341fa 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesFaceDownCreatureAllEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesFaceDownCreatureAllEffect.java @@ -1,41 +1,35 @@ package mage.abilities.effects.common.continuous; +import mage.MageItem; import mage.MageObjectReference; -import mage.ObjectColor; import mage.abilities.Ability; -import mage.abilities.common.TurnFaceUpAbility; import mage.abilities.effects.ContinuousEffectImpl; -import mage.abilities.keyword.MorphAbility; -import mage.cards.Card; -import mage.constants.*; +import mage.constants.Duration; +import mage.constants.Layer; +import mage.constants.Outcome; +import mage.constants.SubLayer; import mage.filter.FilterPermanent; import mage.game.Game; import mage.game.permanent.Permanent; -import java.util.*; +import java.util.List; /** - * TODO: must be reworked to use same face down logic as BecomesFaceDownCreatureEffect - * * @author LevelX2 */ public class BecomesFaceDownCreatureAllEffect extends ContinuousEffectImpl { - protected Map turnFaceUpAbilityMap = new HashMap<>(); protected FilterPermanent filter; public BecomesFaceDownCreatureAllEffect(FilterPermanent filter) { - super(Duration.EndOfGame, Outcome.BecomeCreature); + super(Duration.EndOfGame, Layer.CopyEffects_1, SubLayer.FaceDownEffects_1b, Outcome.BecomeCreature); this.filter = filter; staticText = "turn all " + filter.getMessage() + " face down. (They're 2/2 creatures.)"; } protected BecomesFaceDownCreatureAllEffect(final BecomesFaceDownCreatureAllEffect effect) { super(effect); - for (Map.Entry entry : effect.turnFaceUpAbilityMap.entrySet()) { - this.turnFaceUpAbilityMap.put(entry.getKey(), entry.getValue()); - } this.filter = effect.filter.copy(); } @@ -53,94 +47,31 @@ public void init(Ability source, Game game) { if (!perm.isFaceDown(game) && !perm.isTransformable()) { affectedObjectList.add(new MageObjectReference(perm, game)); perm.setFaceDown(true, game); - // check for Morph - Card card = game.getCard(perm.getId()); - if (card != null) { - for (Ability ability : card.getAbilities(game)) { - if (ability instanceof MorphAbility) { - this.turnFaceUpAbilityMap.put(card.getId(), new TurnFaceUpAbility(((MorphAbility) ability).getFaceUpCosts())); - } - } - } } } } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - boolean targetExists = false; + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { for (MageObjectReference mor : affectedObjectList) { - // TODO: wtf, why it not use a BecomesFaceDownCreatureEffect.makeFaceDownObject and applied by layers?! Looks buggy Permanent permanent = mor.getPermanent(game); if (permanent != null && permanent.isFaceDown(game)) { - targetExists = true; - switch (layer) { - case TypeChangingEffects_4: - permanent.setName(""); - permanent.removeAllSuperTypes(game); - permanent.removeAllCardTypes(game); - permanent.addCardType(game, CardType.CREATURE); - permanent.removeAllSubTypes(game); - permanent.getManaCost().clear(); - break; - case ColorChangingEffects_5: - permanent.getColor(game).setColor(new ObjectColor()); - break; - case AbilityAddingRemovingEffects_6: - Card card = game.getCard(permanent.getId()); // - List abilitiesToRemove = new ArrayList<>(); - for (Ability ability : permanent.getAbilities()) { - - // keep gained abilities from other sources, removes only own (card text) - if (card != null && !card.getAbilities().contains(ability)) { - continue; - } - - // 701.33c - // If a card with morph is manifested, its controller may turn that card face up using - // either the procedure described in rule 702.36e to turn a face-down permanent with morph face up - // or the procedure described above to turn a manifested permanent face up. - // - // so keep all tune face up abilities and other face down compatible - if (ability.getWorksFaceDown()) { - ability.setRuleVisible(false); - continue; - } - - if (!ability.getRuleVisible() && !ability.getEffects().isEmpty()) { - if (ability.getEffects().get(0) instanceof BecomesFaceDownCreatureAllEffect) { - continue; - } - } - abilitiesToRemove.add(ability); - } - permanent.removeAbilities(abilitiesToRemove, source.getSourceId(), game); - if (turnFaceUpAbilityMap.containsKey(permanent.getId())) { - permanent.addAbility(turnFaceUpAbilityMap.get(permanent.getId()), source.getSourceId(), game); - } - break; - case PTChangingEffects_7: - if (sublayer == SubLayer.SetPT_7b) { - permanent.getPower().setModifiedBaseValue(2); - permanent.getToughness().setModifiedBaseValue(2); - } - } + affectedObjects.add(permanent); } } - if (!targetExists) { - discard(); + if (affectedObjects.isEmpty()) { + this.discard(); + return false; } 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.AbilityAddingRemovingEffects_6 || layer == Layer.ColorChangingEffects_5 || layer == Layer.TypeChangingEffects_4; + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; + BecomesFaceDownCreatureEffect.FaceDownType faceDownType = BecomesFaceDownCreatureEffect.findFaceDownType(game, permanent); + BecomesFaceDownCreatureEffect.makeFaceDownObject(game, source.getId(), permanent, faceDownType, null); + } } - } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesFaceDownCreatureEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesFaceDownCreatureEffect.java index 099abc9d1ac4..0d611ba3531a 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesFaceDownCreatureEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesFaceDownCreatureEffect.java @@ -1,5 +1,6 @@ package mage.abilities.effects.common.continuous; +import mage.MageItem; import mage.MageObject; import mage.MageObjectReference; import mage.ObjectColor; @@ -190,17 +191,32 @@ public void init(Ability source, Game game) { } @Override - public boolean apply(Game game, Ability source) { + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Permanent permanent; if (objectReference != null) { permanent = objectReference.getPermanent(game); } else { permanent = game.getPermanent(source.getSourceId()); } - if (permanent != null && permanent.isFaceDown(game)) { + affectedObjects.add(permanent); + } + if (affectedObjects.isEmpty()) { + if (duration == Duration.Custom && foundPermanent) { + this.discard(); + } + return false; + } + return true; + } + + @Override + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + boolean foundPermanentResult = false; + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; if (!foundPermanent) { - foundPermanent = true; + foundPermanentResult = true; switch (faceDownType) { case MANIFESTED: case MANUAL: // sets manifested image // TODO: wtf @@ -220,11 +236,11 @@ public boolean apply(Game game, Ability source) { throw new UnsupportedOperationException("FaceDownType not yet supported: " + faceDownType); } } - makeFaceDownObject(game, source.getSourceId(), permanent, faceDownType, this.additionalAbilities); - } else if (duration == Duration.Custom && foundPermanent) { - discard(); + makeFaceDownObject(game, source.getId(), permanent, faceDownType, additionalAbilities); + } + if (!foundPermanent) { + foundPermanent = foundPermanentResult; } - return true; } // TODO: implement multiple face down types?! diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesSubtypeAllEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesSubtypeAllEffect.java index a0f9ec79ab79..afce80dc6e83 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesSubtypeAllEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesSubtypeAllEffect.java @@ -1,5 +1,6 @@ package mage.abilities.effects.common.continuous; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffectImpl; import mage.constants.*; @@ -8,9 +9,7 @@ import mage.game.Game; import mage.game.permanent.Permanent; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; +import java.util.*; /** * @author LevelX2 @@ -50,24 +49,26 @@ public BecomesSubtypeAllEffect copy() { } @Override - public boolean apply(Game game, Ability source) { - boolean flag = false; - for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game)) { - if (permanent == null) { - continue; + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + affectedObjects.addAll(game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game)); + if (affectedObjects.isEmpty()) { + if (duration == Duration.Custom) { + this.discard(); } - flag = true; + return false; + } + return true; + } + + @Override + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; if (loseOther) { permanent.removeAllCreatureTypes(game); } - for (SubType subtype : subtypes) { - permanent.addSubType(game, subtype); - } + permanent.addSubType(game, subtypes); } - if (!flag && duration == Duration.Custom) { - discard(); - } - return true; } private String setText() { diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesXXConstructSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesXXConstructSourceEffect.java new file mode 100644 index 000000000000..44441ba679d8 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesXXConstructSourceEffect.java @@ -0,0 +1,84 @@ +package mage.abilities.effects.common.continuous; + +import mage.MageItem; +import mage.abilities.Ability; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.constants.*; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.util.CardUtil; + +import java.util.ArrayList; +import java.util.List; + +public class BecomesXXConstructSourceEffect extends ContinuousEffectImpl { + + public BecomesXXConstructSourceEffect(Duration duration) { + super(duration, Outcome.BecomeCreature); + StringBuilder sb = new StringBuilder("{this} becomes an X/X Construct artifact creature"); + if (duration == Duration.EndOfTurn) { + sb.append(" until end of turn"); + } + this.staticText = sb.toString(); + this.dependencyTypes.add(DependencyType.BecomeCreature); + } + + private BecomesXXConstructSourceEffect(final BecomesXXConstructSourceEffect effect) { + super(effect); + } + + @Override + public BecomesXXConstructSourceEffect copy() { + return new BecomesXXConstructSourceEffect(this); + } + + @Override + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; + switch (layer) { + case TypeChangingEffects_4: + if (!permanent.isArtifact(game)) { + permanent.addCardType(game, CardType.ARTIFACT); + } + if (!permanent.isCreature(game)) { + permanent.addCardType(game, CardType.CREATURE); + } + permanent.removeAllCreatureTypes(game); + permanent.addSubType(game, SubType.CONSTRUCT); + break; + case PTChangingEffects_7: + if (sublayer == SubLayer.SetPT_7b) { + int xValue = CardUtil.getSourceCostsTag(game, source, "X", 0); + permanent.getPower().setModifiedBaseValue(xValue); + permanent.getToughness().setModifiedBaseValue(xValue); + } + } + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + Permanent permanent = game.getPermanent(source.getSourceId()); + if (permanent == null) { + return false; + } + affectedObjects.add(permanent); + return true; + } + + @Override + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + List affectedObjects = new ArrayList<>(); + if (queryAffectedObjects(layer, source, game, affectedObjects)) { + applyToObjects(layer, sublayer, source, game, affectedObjects); + return true; + } + return false; + } + + @Override + public boolean hasLayer(Layer layer) { + return layer == Layer.PTChangingEffects_7 || layer == Layer.TypeChangingEffects_4; + } +} diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostAllEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostAllEffect.java index 527d8eb77245..272818af36d4 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostAllEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostAllEffect.java @@ -1,5 +1,6 @@ package mage.abilities.effects.common.continuous; +import mage.MageItem; import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.dynamicvalue.DynamicValue; @@ -17,6 +18,7 @@ import mage.util.CardUtil; import java.util.Iterator; +import java.util.List; import java.util.Locale; /** @@ -114,30 +116,42 @@ public void init(Ability source, Game game) { } @Override - public boolean apply(Game game, Ability source) { + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { if (getAffectedObjectsSet()) { for (Iterator it = affectedObjectList.iterator(); it.hasNext(); ) { // filter may not be used again, because object can have changed filter relevant attributes but still geets boost Permanent permanent = it.next().getPermanent(game); if (permanent != null) { - permanent.addPower(power.calculate(game, source, this)); - permanent.addToughness(toughness.calculate(game, source, this)); + affectedObjects.add(permanent); } else { it.remove(); // no longer on the battlefield, remove reference to object } } } else { setRuntimeData(source, game); - for (Permanent perm : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game)) { - if (!(excludeSource && perm.getId().equals(source.getSourceId())) && selectedByRuntimeData(perm, source, game)) { - perm.addPower(power.calculate(game, source, this)); - perm.addToughness(toughness.calculate(game, source, this)); + for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game)) { + if (!(excludeSource && permanent.getId().equals(source.getSourceId())) && selectedByRuntimeData(permanent, source, game)) { + affectedObjects.add(permanent); } } - + } + if (affectedObjects.isEmpty()) { + if (duration == Duration.Custom) { + this.discard(); + } + return false; } return true; } + @Override + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; + permanent.addPower(power.calculate(game, source, this)); + permanent.addToughness(toughness.calculate(game, source, this)); + } + } + /** * Overwrite this in effect that inherits from this * diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostControlledEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostControlledEffect.java index c1db549eaafe..a2c8f26ebd76 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostControlledEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostControlledEffect.java @@ -1,5 +1,6 @@ package mage.abilities.effects.common.continuous; +import mage.MageItem; import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.dynamicvalue.DynamicValue; @@ -16,6 +17,7 @@ import mage.util.CardUtil; import java.util.Iterator; +import java.util.List; import java.util.Locale; /** @@ -89,29 +91,42 @@ public void init(Ability source, Game game) { } @Override - public boolean apply(Game game, Ability source) { + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { if (getAffectedObjectsSet()) { - for (Iterator it = affectedObjectList.iterator(); it.hasNext(); ) { + for (Iterator it = affectedObjectList.iterator(); it.hasNext(); ) { // filter may not be used again, because object can have changed filter relevant attributes but still geets boost Permanent permanent = it.next().getPermanent(game); if (permanent != null) { - permanent.addPower(power.calculate(game, source, this)); - permanent.addToughness(toughness.calculate(game, source, this)); + affectedObjects.add(permanent); } else { it.remove(); // no longer on the battlefield, remove reference to object } } } else { - for (Permanent perm : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game)) { - if (perm.isControlledBy(source.getControllerId()) - && (!(excludeSource && perm.getId().equals(source.getSourceId())))) { - perm.addPower(power.calculate(game, source, this)); - perm.addToughness(toughness.calculate(game, source, this)); + for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game)) { + if (permanent.isControlledBy(source.getControllerId()) && + !(excludeSource && permanent.getId().equals(source.getSourceId()))) { + affectedObjects.add(permanent); } } } + if (affectedObjects.isEmpty()) { + if (duration == Duration.Custom) { + this.discard(); + } + return false; + } return true; } + @Override + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; + permanent.addPower(power.calculate(game, source, this)); + permanent.addToughness(toughness.calculate(game, source, this)); + } + } + private void setText() { StringBuilder sb = new StringBuilder(); String message = filter.getMessage().toLowerCase(Locale.ENGLISH); diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostEnchantedEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostEnchantedEffect.java index 3e408634d29d..e9a304d3141d 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostEnchantedEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostEnchantedEffect.java @@ -1,5 +1,6 @@ package mage.abilities.effects.common.continuous; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.StaticValue; @@ -12,6 +13,8 @@ import mage.target.targetpointer.FixedTarget; import mage.util.CardUtil; +import java.util.List; + /** * @author BetaSteward_at_googlemail.com, North */ @@ -66,25 +69,33 @@ public void init(Ability source, Game game) { } @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = null; + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { if (getAffectedObjectsSet()) { - permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); - if (permanent == null) { - discard(); - return true; + Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); + if (permanent != null) { + affectedObjects.add(permanent); + } else { + this.discard(); + return false; } } else { Permanent equipment = game.getPermanent(source.getSourceId()); if (equipment != null && equipment.getAttachedTo() != null) { - permanent = game.getPermanent(equipment.getAttachedTo()); + Permanent attachedTo = game.getPermanent(equipment.getAttachedTo()); + if (attachedTo != null) { + affectedObjects.add(attachedTo); + } } } - if (permanent != null) { + return !affectedObjects.isEmpty(); + } + + @Override + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; permanent.addPower(power.calculate(game, source, this)); permanent.addToughness(toughness.calculate(game, source, this)); } - return true; } - } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostEquippedEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostEquippedEffect.java index 70e9badbd924..020f86e1f2a3 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostEquippedEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostEquippedEffect.java @@ -1,5 +1,6 @@ package mage.abilities.effects.common.continuous; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.StaticValue; @@ -13,7 +14,7 @@ import mage.target.targetpointer.FixedTarget; import mage.util.CardUtil; -import java.util.Optional; +import java.util.List; /** * @author BetaSteward_at_googlemail.com @@ -70,23 +71,30 @@ public void init(Ability source, Game game) { } @Override - public boolean apply(Game game, Ability source) { - Permanent creature; + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { if (fixedTarget) { - creature = game.getPermanent(getTargetPointer().getFirst(game, source)); + Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); + if (permanent != null) { + affectedObjects.add(permanent); + } } else { - creature = Optional - .ofNullable(source) - .map(Ability::getSourceId) - .map(game::getPermanent) - .map(Permanent::getAttachedTo) - .map(game::getPermanent) - .orElse(null); + Permanent equipment = game.getPermanent(source.getSourceId()); + if (equipment != null && equipment.getAttachedTo() != null) { + Permanent attachedTo = game.getPermanent(equipment.getAttachedTo()); + if (attachedTo != null) { + affectedObjects.add(attachedTo); + } + } } - if (creature != null) { - creature.addPower(power.calculate(game, source, this)); - creature.addToughness(toughness.calculate(game, source, this)); + return !affectedObjects.isEmpty(); + } + + @Override + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; + permanent.addPower(power.calculate(game, source, this)); + permanent.addToughness(toughness.calculate(game, source, this)); } - return true; } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostOpponentsEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostOpponentsEffect.java index 4c4633e27692..df2865135bc6 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostOpponentsEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostOpponentsEffect.java @@ -1,5 +1,6 @@ package mage.abilities.effects.common.continuous; +import mage.MageItem; import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffectImpl; @@ -14,6 +15,7 @@ import mage.util.CardUtil; import java.util.Iterator; +import java.util.List; import java.util.Set; import java.util.UUID; @@ -60,31 +62,44 @@ public void init(Ability source, Game game) { } @Override - public boolean apply(Game game, Ability source) { + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Set opponents = game.getOpponents(source.getControllerId()); if (getAffectedObjectsSet()) { - for (Iterator it = affectedObjectList.iterator(); it.hasNext(); ) { // filter may not be used again, because object can have changed filter relevant attributes but still geets boost - Permanent perm = it.next().getPermanent(game); - if (perm != null) { - if (opponents.contains(perm.getControllerId())) { - perm.addPower(power); - perm.addToughness(toughness); + for (Iterator it = affectedObjectList.iterator(); it.hasNext(); ) { // filter may not be used again, because object can have changed filter relevant attributes but still gets boost + Permanent permanent = it.next().getPermanent(game); + if (permanent != null) { + if (opponents.contains(permanent.getControllerId())) { + affectedObjects.add(permanent); } } else { it.remove(); } } } else { - for (Permanent perm : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game)) { - if (opponents.contains(perm.getControllerId())) { - perm.addPower(power); - perm.addToughness(toughness); + for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game)) { + if (opponents.contains(permanent.getControllerId())) { + affectedObjects.add(permanent); } } } + if (affectedObjects.isEmpty()) { + if (getAffectedObjectsSet()) { + this.discard(); + } + return false; + } return true; } + @Override + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; + permanent.addPower(power); + permanent.addToughness(toughness); + } + } + private void setText() { StringBuilder sb = new StringBuilder(); sb.append(filter.getMessage()); diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostPairedEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostPairedEffect.java index 5d003567fc17..f0903679ce23 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostPairedEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostPairedEffect.java @@ -1,6 +1,7 @@ package mage.abilities.effects.common.continuous; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffectImpl; import mage.constants.Duration; @@ -10,13 +11,15 @@ import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.List; + /** * @author noxx */ public class BoostPairedEffect extends ContinuousEffectImpl { - private int power; - private int toughness; + private final int power; + private final int toughness; public BoostPairedEffect(int power, int toughness, String rule) { super(Duration.WhileOnBattlefield, Layer.PTChangingEffects_7, SubLayer.ModifyPT_7c, Outcome.BoostCreature); @@ -37,19 +40,24 @@ public BoostPairedEffect copy() { } @Override - public boolean apply(Game game, Ability source) { + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Permanent permanent = game.getPermanent(source.getSourceId()); if (permanent != null && permanent.getPairedCard() != null) { Permanent paired = permanent.getPairedCard().getPermanent(game); if (paired != null) { - permanent.addPower(power); - permanent.addToughness(toughness); - paired.addPower(power); - paired.addToughness(toughness); - return true; + affectedObjects.add(permanent); + affectedObjects.add(paired); } } - return false; + return !affectedObjects.isEmpty(); } + @Override + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; + permanent.addPower(power); + permanent.addToughness(toughness); + } + } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostSourceEffect.java index d5b50536ff20..bd58375efb41 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostSourceEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostSourceEffect.java @@ -1,5 +1,6 @@ package mage.abilities.effects.common.continuous; +import mage.MageItem; import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.dynamicvalue.DynamicValue; @@ -13,6 +14,8 @@ import mage.game.permanent.Permanent; import mage.util.CardUtil; +import java.util.List; + /** * @author BetaSteward_at_googlemail.com */ @@ -62,18 +65,35 @@ public void init(Ability source, Game game) { } @Override - public boolean apply(Game game, Ability source) { - Permanent target; + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { if (getAffectedObjectsSet()) { - target = affectedObjectList.get(0).getPermanent(game); + for (MageObjectReference mor : affectedObjectList) { + Permanent permanent = mor.getPermanent(game); + if (permanent != null) { + affectedObjects.add(permanent); + } + } } else { - target = game.getPermanent(source.getSourceId()); + Permanent permanent = game.getPermanent(source.getSourceId()); + if (permanent != null) { + affectedObjects.add(permanent); + } + } + if (affectedObjects.isEmpty()) { + if (getAffectedObjectsSet()) { + this.discard(); + } + return false; } - if (target != null) { - target.addPower(power.calculate(game, source, this)); - target.addToughness(toughness.calculate(game, source, this)); - return true; + return true; + } + + @Override + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; + permanent.addPower(power.calculate(game, source, this)); + permanent.addToughness(toughness.calculate(game, source, this)); } - return false; } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostTargetEffect.java index fccd2ce6d5a0..40d5a22470cb 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostTargetEffect.java @@ -1,5 +1,6 @@ package mage.abilities.effects.common.continuous; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.Mode; import mage.abilities.dynamicvalue.DynamicValue; @@ -12,6 +13,7 @@ import mage.game.permanent.Permanent; import mage.util.CardUtil; +import java.util.List; import java.util.UUID; /** @@ -62,17 +64,23 @@ public void init(Ability source, Game game) { } @Override - public boolean apply(Game game, Ability source) { - int affectedTargets = 0; - for (UUID permanentId : getTargetPointer().getTargets(game, source)) { - Permanent target = game.getPermanent(permanentId); - if (target != null && target.isCreature(game)) { - target.addPower(power.calculate(game, source, this)); - target.addToughness(toughness.calculate(game, source, this)); - affectedTargets++; + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + for (UUID targetId : getTargetPointer().getTargets(game, source)) { + Permanent permanent = game.getPermanent(targetId); + if (permanent != null && permanent.isCreature(game)) { + affectedObjects.add(permanent); } } - return affectedTargets > 0; + return !affectedObjects.isEmpty(); + } + + @Override + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; + permanent.addPower(power.calculate(game, source, this)); + permanent.addToughness(toughness.calculate(game, source, this)); + } } @Override diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/CantBeSacrificedSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/CantBeSacrificedSourceEffect.java index 447767db12a8..6e5b5fa3ad4c 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/CantBeSacrificedSourceEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/CantBeSacrificedSourceEffect.java @@ -1,5 +1,6 @@ package mage.abilities.effects.common.continuous; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffectImpl; import mage.constants.Duration; @@ -9,6 +10,8 @@ import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.List; + /** * @author xenohedron */ @@ -29,7 +32,14 @@ public CantBeSacrificedSourceEffect copy() { } @Override - public boolean apply(Game game, Ability source) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + ((Permanent) object).setCanBeSacrificed(false); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Permanent permanent = game.getPermanentEntering(source.getSourceId()); if (permanent == null) { permanent = source.getSourcePermanentIfItStillExists(game); @@ -38,8 +48,7 @@ public boolean apply(Game game, Ability source) { discard(); return false; } - permanent.setCanBeSacrificed(false); + affectedObjects.add(permanent); return true; } - } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/CantGainLifeAllEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/CantGainLifeAllEffect.java index 0d363ea0da23..4f7c255b733a 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/CantGainLifeAllEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/CantGainLifeAllEffect.java @@ -1,5 +1,6 @@ package mage.abilities.effects.common.continuous; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffectImpl; import mage.constants.*; @@ -7,6 +8,7 @@ import mage.game.permanent.Permanent; import mage.players.Player; +import java.util.List; import java.util.Optional; import java.util.UUID; @@ -15,7 +17,7 @@ */ public class CantGainLifeAllEffect extends ContinuousEffectImpl { - private TargetController targetController; + private final TargetController targetController; public CantGainLifeAllEffect() { this(Duration.WhileOnBattlefield); @@ -43,7 +45,14 @@ public CantGainLifeAllEffect copy() { } @Override - public boolean apply(Game game, Ability source) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + ((Player) object).setCanGainLife(false); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Player controller = game.getPlayer(source.getControllerId()); if (controller == null) { return false; @@ -56,7 +65,7 @@ public boolean apply(Game game, Ability source) { for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { Player player = game.getPlayer(playerId); if (player != null && !player.equals(controller)) { - player.setCanGainLife(false); + affectedObjects.add(player); } } break; @@ -65,7 +74,7 @@ public boolean apply(Game game, Ability source) { if (controller.hasOpponent(playerId, game)) { Player player = game.getPlayer(playerId); if (player != null) { - player.setCanGainLife(false); + affectedObjects.add(player); } } } @@ -74,7 +83,7 @@ public boolean apply(Game game, Ability source) { for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { Player player = game.getPlayer(playerId); if (player != null) { - player.setCanGainLife(false); + affectedObjects.add(player); } } break; @@ -83,7 +92,7 @@ public boolean apply(Game game, Ability source) { .ofNullable(source.getSourcePermanentIfItStillExists(game)) .map(Permanent::getAttachedTo) .map(game::getPlayer) - .ifPresent(player -> player.setCanGainLife(false)); + .ifPresent(affectedObjects::add); } return true; } @@ -112,7 +121,7 @@ private String setText() { if (duration == Duration.EndOfTurn) { sb.append("this turn"); } else { - sb.append(duration.toString()); + sb.append(duration); } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/CantGainLifeRestOfGameTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/CantGainLifeRestOfGameTargetEffect.java index d2e8ef09b74c..a870debf1cea 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/CantGainLifeRestOfGameTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/CantGainLifeRestOfGameTargetEffect.java @@ -1,5 +1,6 @@ package mage.abilities.effects.common.continuous; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffectImpl; import mage.constants.Duration; @@ -9,6 +10,8 @@ import mage.game.Game; import mage.players.Player; +import java.util.List; + /** * @author Susucr */ @@ -29,11 +32,19 @@ public CantGainLifeRestOfGameTargetEffect copy() { } @Override - public boolean apply(Game game, Ability source) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + ((Player) object).setCanGainLife(false); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Player player = game.getPlayer(this.getTargetPointer().getFirst(game, source)); if (player != null) { - player.setCanGainLife(false); + affectedObjects.add(player); + return true; } - return true; + return false; } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/CantGainLifeTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/CantGainLifeTargetEffect.java index 1fb7ae08c03c..4f2f3ebad3fd 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/CantGainLifeTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/CantGainLifeTargetEffect.java @@ -2,8 +2,7 @@ package mage.abilities.effects.common.continuous; -import java.util.UUID; - +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffectImpl; import mage.constants.Duration; @@ -13,6 +12,9 @@ import mage.game.Game; import mage.players.Player; +import java.util.List; +import java.util.UUID; + /** * @author LevelX2 */ @@ -42,14 +44,21 @@ public CantGainLifeTargetEffect copy() { } @Override - public boolean apply(Game game, Ability source) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + ((Player) object).setCanGainLife(false); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { for (UUID playerId : this.getTargetPointer().getTargets(game, source)) { Player targetPlayer = game.getPlayer(playerId); if (targetPlayer != null) { - targetPlayer.setCanGainLife(false); + affectedObjects.add(targetPlayer); } } - return true; + return !affectedObjects.isEmpty(); } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/CastFromHandWithoutPayingManaCostEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/CastFromHandWithoutPayingManaCostEffect.java index 0a561f533a48..f4467b7065f1 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/CastFromHandWithoutPayingManaCostEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/CastFromHandWithoutPayingManaCostEffect.java @@ -1,5 +1,6 @@ package mage.abilities.effects.common.continuous; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.condition.CompoundCondition; import mage.abilities.condition.Condition; @@ -16,6 +17,8 @@ import mage.game.Game; import mage.players.Player; +import java.util.List; + public class CastFromHandWithoutPayingManaCostEffect extends ContinuousEffectImpl { private final AlternativeCostSourceAbility alternativeCastingCostAbility; @@ -29,7 +32,7 @@ public CastFromHandWithoutPayingManaCostEffect(FilterCard filter, boolean fromHa } public CastFromHandWithoutPayingManaCostEffect(FilterCard filter, boolean fromHand, Duration duration) { - super(duration, Outcome.Detriment); + super(duration, Layer.RulesEffects, SubLayer.NA, Outcome.Detriment); Condition condition; if (fromHand) { condition = new CompoundCondition(SourceIsSpellCondition.instance, IsBeingCastFromHandCondition.instance); @@ -53,23 +56,21 @@ public CastFromHandWithoutPayingManaCostEffect copy() { } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Player player = (Player) object; + alternativeCastingCostAbility.setSourceId(source.getSourceId()); + player.getAlternativeSourceCosts().add(alternativeCastingCostAbility); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Player controller = game.getPlayer(source.getControllerId()); if (controller == null) { return false; } - alternativeCastingCostAbility.setSourceId(source.getSourceId()); - controller.getAlternativeSourceCosts().add(alternativeCastingCostAbility); + affectedObjects.add(controller); return true; } - - @Override - public boolean apply(Game game, Ability source) { - return false; - } - - @Override - public boolean hasLayer(Layer layer) { - return layer == Layer.RulesEffects; - } -} \ No newline at end of file +} diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/ChangeMaxNumberThatCanAttackSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/ChangeMaxNumberThatCanAttackSourceEffect.java index 008ded32442e..23872baa8d47 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/ChangeMaxNumberThatCanAttackSourceEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/ChangeMaxNumberThatCanAttackSourceEffect.java @@ -1,5 +1,6 @@ package mage.abilities.effects.common.continuous; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffectImpl; import mage.constants.Duration; @@ -10,6 +11,8 @@ import mage.players.Player; import mage.util.CardUtil; +import java.util.List; + /** * @author LevelX2 */ @@ -35,15 +38,19 @@ public ChangeMaxNumberThatCanAttackSourceEffect copy() { } @Override - public boolean apply(Game game, Ability source) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + ((Player) object).setMaxAttackedBy(maxAttackedBy); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Player controller = game.getPlayer(source.getControllerId()); - if (controller == null) { + if (controller == null || controller.getMaxAttackedBy() < maxAttackedBy) { return false; } - // Change the rule - if (controller.getMaxAttackedBy() > maxAttackedBy) { - controller.setMaxAttackedBy(maxAttackedBy); - } + affectedObjects.add(controller); return true; } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/ControlEnchantedEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/ControlEnchantedEffect.java index 4a265da274b8..ba8c65f2b101 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/ControlEnchantedEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/ControlEnchantedEffect.java @@ -1,5 +1,6 @@ package mage.abilities.effects.common.continuous; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffectImpl; import mage.constants.Duration; @@ -9,6 +10,8 @@ import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.List; + /** * @author nantuko */ @@ -33,7 +36,14 @@ public ControlEnchantedEffect copy() { } @Override - public boolean apply(Game game, Ability source) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + ((Permanent) object).changeControllerId(source.getControllerId(), game, source); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Permanent enchantment = source.getSourcePermanentIfItStillExists(game); if (enchantment == null) { return false; @@ -42,7 +52,7 @@ public boolean apply(Game game, Ability source) { if (permanent == null) { return false; } - permanent.changeControllerId(source.getControllerId(), game, source); + affectedObjects.add(permanent); return true; } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/CreaturesBecomeOtherTypeEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/CreaturesBecomeOtherTypeEffect.java index 1b0d72858476..d2d3c6c1ba54 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/CreaturesBecomeOtherTypeEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/CreaturesBecomeOtherTypeEffect.java @@ -1,17 +1,20 @@ package mage.abilities.effects.common.continuous; +import mage.MageItem; import mage.abilities.Ability; -import mage.abilities.Mode; import mage.abilities.effects.ContinuousEffectImpl; import mage.constants.*; import mage.filter.FilterPermanent; import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.ArrayList; +import java.util.List; + public class CreaturesBecomeOtherTypeEffect extends ContinuousEffectImpl { protected final FilterPermanent filter; - private final SubType subType; + protected final SubType subType; public CreaturesBecomeOtherTypeEffect(FilterPermanent filter, SubType subType, Duration duration) { super(duration, Outcome.Neutral); @@ -20,7 +23,7 @@ public CreaturesBecomeOtherTypeEffect(FilterPermanent filter, SubType subType, D this.dependendToTypes.add(DependencyType.BecomeCreature); // Opalescence and Starfield of Nyx this.staticText = this.filter.getMessage() + " is " + this.subType.getIndefiniteArticle() - + " " + this.subType.toString() + " in addition to its other types"; + + " " + this.subType + " in addition to its other types"; } protected CreaturesBecomeOtherTypeEffect(final CreaturesBecomeOtherTypeEffect effect) { @@ -30,28 +33,35 @@ protected CreaturesBecomeOtherTypeEffect(final CreaturesBecomeOtherTypeEffect ef } @Override - public boolean apply(Game game, Ability source) { - return false; + public CreaturesBecomeOtherTypeEffect copy() { + return new CreaturesBecomeOtherTypeEffect(this); } @Override - public CreaturesBecomeOtherTypeEffect copy() { - return new CreaturesBecomeOtherTypeEffect(this); + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + ((Permanent) object).addSubType(game, this.subType); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + affectedObjects.addAll(game.getBattlefield().getActivePermanents(this.filter, source.getControllerId(), game)); + return !affectedObjects.isEmpty(); } @Override public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - if (layer == Layer.TypeChangingEffects_4) { - for (Permanent object : game.getBattlefield().getActivePermanents(this.filter, source.getControllerId(), game)) { - object.addSubType(game, this.subType); - } + List affectedObjects = new ArrayList<>(); + if (queryAffectedObjects(layer, source, game, affectedObjects)) { + applyToObjects(layer, sublayer, source, game, affectedObjects); + return true; } - - return true; + return false; } @Override public boolean hasLayer(Layer layer) { return layer == Layer.TypeChangingEffects_4; } -} \ No newline at end of file +} diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/CreaturesCantGetOrHaveAbilityEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/CreaturesCantGetOrHaveAbilityEffect.java index 00be50e495e3..8cc8b2c84a00 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/CreaturesCantGetOrHaveAbilityEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/CreaturesCantGetOrHaveAbilityEffect.java @@ -1,5 +1,6 @@ package mage.abilities.effects.common.continuous; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffectImpl; import mage.constants.DependencyType; @@ -13,6 +14,8 @@ import mage.game.permanent.Permanent; import mage.players.Player; +import java.util.List; + /** * @author LevelX2 */ @@ -26,7 +29,7 @@ public CreaturesCantGetOrHaveAbilityEffect(Ability ability, Duration duration) { } public CreaturesCantGetOrHaveAbilityEffect(Ability ability, Duration duration, FilterCreaturePermanent filter) { - super(duration, Outcome.Detriment); + super(duration, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.Detriment); this.ability = ability; this.filter = filter; staticText = filter.getMessage() + " lose " + ability.getRule() + " and can't have or gain " + ability.getRule(); @@ -45,27 +48,19 @@ public CreaturesCantGetOrHaveAbilityEffect copy() { } @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game)) { - if (permanent != null) { - permanent.removeAbility(ability, source.getSourceId(), game); - } - } - return true; + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + ((Permanent) object).removeAbility(ability, source.getSourceId(), game); } - return false; - - } - - @Override - public boolean apply(Game game, Ability source) { - return false; } @Override - public boolean hasLayer(Layer layer) { - return layer == Layer.AbilityAddingRemovingEffects_6; + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return false; + } + affectedObjects.addAll(game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game)); + return !affectedObjects.isEmpty(); } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/DontLoseByZeroOrLessLifeEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/DontLoseByZeroOrLessLifeEffect.java index 2952ef1711fb..7812847dac73 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/DontLoseByZeroOrLessLifeEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/DontLoseByZeroOrLessLifeEffect.java @@ -2,6 +2,7 @@ package mage.abilities.effects.common.continuous; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffectImpl; import mage.constants.Duration; @@ -11,6 +12,8 @@ import mage.game.Game; import mage.players.Player; +import java.util.List; + /** * @author LevelX2 */ @@ -32,13 +35,19 @@ public DontLoseByZeroOrLessLifeEffect copy() { } @Override - public boolean apply(Game game, Ability source) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + ((Player) object).setLoseByZeroOrLessLife(false); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { - controller.setLoseByZeroOrLessLife(false); + affectedObjects.add(controller); return true; } return false; } - -} \ No newline at end of file +} diff --git a/Mage/src/main/java/mage/abilities/effects/common/cost/CostModificationEffectImpl.java b/Mage/src/main/java/mage/abilities/effects/common/cost/CostModificationEffectImpl.java index 8fb7bfa3ccf9..db3b5e6a3123 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/cost/CostModificationEffectImpl.java +++ b/Mage/src/main/java/mage/abilities/effects/common/cost/CostModificationEffectImpl.java @@ -1,13 +1,11 @@ package mage.abilities.effects.common.cost; -import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.CostModificationEffect; import mage.constants.CostModificationType; import mage.constants.Duration; import mage.constants.EffectType; import mage.constants.Outcome; -import mage.game.Game; /** * Simple implementation of a {@link CostModificationEffect} offering simplified @@ -40,19 +38,6 @@ protected CostModificationEffectImpl(final CostModificationEffectImpl effect) { this.worksOnStackOnly = effect.worksOnStackOnly; } - /** - * Overridden and 'no-op' implementation put in place. - * - * @param game - * @param source - * @return - * @see #apply(mage.game.Game, mage.abilities.Ability, mage.abilities.Ability) - */ - @Override - public final boolean apply(Game game, Ability source) { - return false; - } - @Override public CostModificationType getModificationType() { return this.modificationType; diff --git a/Mage/src/main/java/mage/abilities/effects/common/ruleModifying/CombatDamageByToughnessAllEffect.java b/Mage/src/main/java/mage/abilities/effects/common/ruleModifying/CombatDamageByToughnessAllEffect.java index 3322d3ce9dad..00dbc29d45e3 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/ruleModifying/CombatDamageByToughnessAllEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/ruleModifying/CombatDamageByToughnessAllEffect.java @@ -1,5 +1,6 @@ package mage.abilities.effects.common.ruleModifying; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffectImpl; import mage.constants.Duration; @@ -9,6 +10,9 @@ import mage.filter.StaticFilters; import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; +import mage.game.permanent.Permanent; + +import java.util.List; /** * @author TheElk801, xanderhall @@ -46,9 +50,18 @@ public CombatDamageByToughnessAllEffect copy() { } @Override - public boolean apply(Game game, Ability source) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { game.getCombat().setUseToughnessForDamage(true); game.getCombat().addUseToughnessForDamageFilter(filter); + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + Permanent permanent = game.getPermanent(source.getSourceId()); + if (permanent == null) { + return false; + } + affectedObjects.add(permanent); return true; } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/ruleModifying/CombatDamageByToughnessControlledEffect.java b/Mage/src/main/java/mage/abilities/effects/common/ruleModifying/CombatDamageByToughnessControlledEffect.java index d11473e15499..31ca452eaa6f 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/ruleModifying/CombatDamageByToughnessControlledEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/ruleModifying/CombatDamageByToughnessControlledEffect.java @@ -1,5 +1,6 @@ package mage.abilities.effects.common.ruleModifying; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffectImpl; import mage.constants.Duration; @@ -10,6 +11,9 @@ import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; +import mage.game.permanent.Permanent; + +import java.util.List; /** * @author TheElk801, xenohedron @@ -49,11 +53,20 @@ public CombatDamageByToughnessControlledEffect copy() { } @Override - public boolean apply(Game game, Ability source) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { FilterCreaturePermanent filterPermanent = filter.copy(); filterPermanent.add(new ControllerIdPredicate(source.getControllerId())); game.getCombat().setUseToughnessForDamage(true); game.getCombat().addUseToughnessForDamageFilter(filterPermanent); + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + Permanent permanent = game.getPermanent(source.getSourceId()); + if (permanent == null) { + return false; + } + affectedObjects.add(permanent); return true; } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/ruleModifying/CombatDamageByToughnessSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/ruleModifying/CombatDamageByToughnessSourceEffect.java index ffbd8c9476a9..2483230d389e 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/ruleModifying/CombatDamageByToughnessSourceEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/ruleModifying/CombatDamageByToughnessSourceEffect.java @@ -1,5 +1,6 @@ package mage.abilities.effects.common.ruleModifying; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffectImpl; import mage.constants.Duration; @@ -11,6 +12,8 @@ import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.List; + public class CombatDamageByToughnessSourceEffect extends ContinuousEffectImpl { public CombatDamageByToughnessSourceEffect(Duration duration) { @@ -28,17 +31,23 @@ public CombatDamageByToughnessSourceEffect copy() { } @Override - public boolean apply(Game game, Ability source) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects){ + Permanent permanent = (Permanent) object; + FilterCreaturePermanent filter = new FilterCreaturePermanent(); + filter.add(new MageObjectReferencePredicate(permanent.getId(), game)); + game.getCombat().setUseToughnessForDamage(true); + game.getCombat().addUseToughnessForDamageFilter(filter); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Permanent permanent = source.getSourcePermanentIfItStillExists(game); if (permanent == null) { return false; } - - FilterCreaturePermanent filter = new FilterCreaturePermanent(); - filter.add(new MageObjectReferencePredicate(permanent.getId(), game)); - game.getCombat().setUseToughnessForDamage(true); - game.getCombat().addUseToughnessForDamageFilter(filter); - + affectedObjects.add(permanent); return true; } diff --git a/Mage/src/main/java/mage/abilities/effects/common/ruleModifying/CombatDamageByToughnessTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/ruleModifying/CombatDamageByToughnessTargetEffect.java index a55bf533ba69..182cf44191ff 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/ruleModifying/CombatDamageByToughnessTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/ruleModifying/CombatDamageByToughnessTargetEffect.java @@ -1,5 +1,6 @@ package mage.abilities.effects.common.ruleModifying; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.Mode; import mage.abilities.effects.ContinuousEffectImpl; @@ -12,8 +13,8 @@ import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.List; import java.util.Objects; -import java.util.Set; import java.util.stream.Collectors; public class CombatDamageByToughnessTargetEffect extends ContinuousEffectImpl { @@ -36,18 +37,21 @@ public CombatDamageByToughnessTargetEffect copy() { } @Override - public boolean apply(Game game, Ability source) { - Set set = getTargetPointer().getTargets(game, source).stream() - .map(game::getPermanent) - .filter(Objects::nonNull) - .collect(Collectors.toSet()); - + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + List permanents = affectedObjects.stream().map(Permanent.class::cast).collect(Collectors.toList()); FilterCreaturePermanent filter = new FilterCreaturePermanent(); - filter.add(new PermanentReferenceInCollectionPredicate(set, game)); + filter.add(new PermanentReferenceInCollectionPredicate(permanents, game)); game.getCombat().setUseToughnessForDamage(true); game.getCombat().addUseToughnessForDamageFilter(filter); + } - return true; + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + affectedObjects.addAll(getTargetPointer().getTargets(game, source).stream() + .map(game::getPermanent) + .filter(Objects::nonNull) + .collect(Collectors.toList())); + return !affectedObjects.isEmpty(); } @Override @@ -55,7 +59,7 @@ public String getText(Mode mode) { if (staticText != null && !staticText.isEmpty()) { return staticText; } - return (duration.toString().isEmpty() ? "" : duration.toString() + ", ") + return (duration.toString().isEmpty() ? "" : duration + ", ") + getTargetPointer().describeTargets(mode.getTargets(), "that creature") + " assigns combat damage equal to its toughness rather than its power"; } diff --git a/Mage/src/main/java/mage/abilities/effects/keyword/AscendEffect.java b/Mage/src/main/java/mage/abilities/effects/keyword/AscendEffect.java index c338c02c49c1..4cc376049dd5 100644 --- a/Mage/src/main/java/mage/abilities/effects/keyword/AscendEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/keyword/AscendEffect.java @@ -28,6 +28,10 @@ public AscendEffect copy() { @Override public boolean apply(Game game, Ability source) { - return AscendAbility.checkAscend(game, source, true); + if (AscendAbility.checkAscend(game, source, true)) { + AscendAbility.applyAscend(game, game.getPlayer(source.getControllerId())); + return true; + } + return false; } } diff --git a/Mage/src/main/java/mage/abilities/keyword/AscendAbility.java b/Mage/src/main/java/mage/abilities/keyword/AscendAbility.java index 5cbbde2208ed..bf1e6feb988c 100644 --- a/Mage/src/main/java/mage/abilities/keyword/AscendAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/AscendAbility.java @@ -1,6 +1,7 @@ package mage.abilities.keyword; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousEffectImpl; @@ -15,6 +16,8 @@ import mage.game.Game; import mage.players.Player; +import java.util.List; + /** * @author LevelX2 */ @@ -40,8 +43,7 @@ public static boolean checkAscend(Game game, Ability source, boolean verbose) { if (controller != null) { if (!controller.hasDesignation(DesignationType.CITYS_BLESSING)) { if (game.getBattlefield().countAll(StaticFilters.FILTER_PERMANENT, controller.getId(), game) > 9) { - controller.addDesignation(new CitysBlessing()); - game.informPlayers(controller.getLogName() + " gets the city's blessing for the rest of the game."); + return true; } else { if (verbose) { game.informPlayers(controller.getLogName() + " does not get the city's blessing."); @@ -52,11 +54,15 @@ public static boolean checkAscend(Game game, Ability source, boolean verbose) { game.informPlayers(controller.getLogName() + " already has the city's blessing."); } } - return true; } return false; } + public static void applyAscend(Game game, Player player) { + player.addDesignation(new CitysBlessing()); + game.informPlayers(player.getLogName() + " gets the city's blessing for the rest of the game."); + } + @Override public String getRule() { return ASCEND_RULE; @@ -76,8 +82,20 @@ protected AscendContinuousEffect(final AscendContinuousEffect effect) { } @Override - public boolean apply(Game game, Ability source) { - return AscendAbility.checkAscend(game, source, false); + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Player player = (Player) object; + AscendAbility.applyAscend(game, player); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + if (AscendAbility.checkAscend(game, source, false)) { + affectedObjects.add(game.getPlayer(source.getControllerId())); + return true; + } + return false; } @Override diff --git a/Mage/src/main/java/mage/abilities/keyword/DayboundAbility.java b/Mage/src/main/java/mage/abilities/keyword/DayboundAbility.java index c6dcfc78542c..0bec6e46ea7b 100644 --- a/Mage/src/main/java/mage/abilities/keyword/DayboundAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/DayboundAbility.java @@ -1,11 +1,15 @@ package mage.abilities.keyword; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.StaticAbility; import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.hint.common.DayNightHint; import mage.constants.*; import mage.game.Game; +import mage.game.permanent.Permanent; + +import java.util.List; /** * @author TheElk801 @@ -49,12 +53,21 @@ public DayboundEffect copy() { } @Override - public boolean apply(Game game, Ability source) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { if (!game.hasDayNight()) { // 702.145d // Any time a player controls a permanent with daybound, if it’s neither day nor night, it becomes day. game.setDaytime(true); } - return true; + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { + Permanent permanent = game.getPermanent(source.getSourceId()); + if (permanent != null) { + affectedObjects.add(permanent); + return true; + } + return false; } } diff --git a/Mage/src/main/java/mage/game/command/emblems/DackFaydenEmblem.java b/Mage/src/main/java/mage/game/command/emblems/DackFaydenEmblem.java index faa2636f36da..a91d3e637d15 100644 --- a/Mage/src/main/java/mage/game/command/emblems/DackFaydenEmblem.java +++ b/Mage/src/main/java/mage/game/command/emblems/DackFaydenEmblem.java @@ -1,5 +1,6 @@ package mage.game.command.emblems; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.Mode; import mage.abilities.SpellAbility; @@ -137,14 +138,21 @@ public DackFaydenEmblemEffect copy() { } @Override - public boolean apply(Game game, Ability source) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + ((Permanent) object).changeControllerId(source.getControllerId(), game, source); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { for (UUID permanentId : fixedTargets.getTargets(game, source)) { Permanent permanent = game.getPermanent(permanentId); if (permanent != null) { - permanent.changeControllerId(source.getControllerId(), game, source); + affectedObjects.add(permanent); } } - return true; + return !affectedObjects.isEmpty(); } public void setTargets(List targetedPermanents, Game game) { diff --git a/Mage/src/main/java/mage/game/permanent/token/AlienAngelToken.java b/Mage/src/main/java/mage/game/permanent/token/AlienAngelToken.java index c871d9e464aa..b5d932971b83 100644 --- a/Mage/src/main/java/mage/game/permanent/token/AlienAngelToken.java +++ b/Mage/src/main/java/mage/game/permanent/token/AlienAngelToken.java @@ -1,6 +1,7 @@ package mage.game.permanent.token; import mage.MageInt; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.SpellCastOpponentTriggeredAbility; import mage.abilities.effects.ContinuousEffectImpl; @@ -11,6 +12,8 @@ import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.List; + /** * @author TheElk801 */ @@ -59,14 +62,22 @@ public AlienAngelTokenEffect copy() { } @Override - public boolean apply(Game game, Ability source) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Permanent permanent = (Permanent) object; + permanent.removeAllSubTypes(game, SubTypeSet.CreatureType); + permanent.removeCardType(game, CardType.CREATURE); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Permanent permanent = source.getSourcePermanentIfItStillExists(game); if (permanent == null) { discard(); return false; } - permanent.removeAllSubTypes(game, SubTypeSet.CreatureType); - permanent.removeCardType(game, CardType.CREATURE); + affectedObjects.add(permanent); return true; } } diff --git a/Mage/src/main/java/mage/game/permanent/token/DaxosSpiritToken.java b/Mage/src/main/java/mage/game/permanent/token/DaxosSpiritToken.java index ffe198aff1ed..80f70c27bb4a 100644 --- a/Mage/src/main/java/mage/game/permanent/token/DaxosSpiritToken.java +++ b/Mage/src/main/java/mage/game/permanent/token/DaxosSpiritToken.java @@ -1,6 +1,7 @@ package mage.game.permanent.token; import mage.MageInt; +import mage.MageItem; import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; @@ -11,6 +12,8 @@ import mage.game.permanent.Permanent; import mage.players.Player; +import java.util.List; + /** * @author spjspj */ @@ -54,7 +57,18 @@ public DaxosSpiritSetPTEffect copy() { } @Override - public boolean apply(Game game, Ability source) { + public void applyToObjects(Layer layer, SubLayer sublayer, Ability source, Game game, List affectedObjects) { + for (MageItem object : affectedObjects) { + Player controller = game.getPlayer(source.getControllerId()); + Permanent permanent = (Permanent) object; + int amount = controller.getCountersCount(CounterType.EXPERIENCE); + permanent.getPower().setModifiedBaseValue(amount); + permanent.getToughness().setModifiedBaseValue(amount); + } + } + + @Override + public boolean queryAffectedObjects(Layer layer, Ability source, Game game, List affectedObjects) { Player controller = game.getPlayer(source.getControllerId()); if (controller == null) { return false; @@ -64,10 +78,7 @@ public boolean apply(Game game, Ability source) { discard(); return false; } - - int amount = controller.getCountersCount(CounterType.EXPERIENCE); - permanent.getPower().setModifiedBaseValue(amount); - permanent.getToughness().setModifiedBaseValue(amount); + affectedObjects.add(permanent); return true; } }