diff --git a/Mage.Sets/src/mage/cards/t/TeferisProtection.java b/Mage.Sets/src/mage/cards/t/TeferisProtection.java index 1c606c02f2d..a08ad3ba122 100644 --- a/Mage.Sets/src/mage/cards/t/TeferisProtection.java +++ b/Mage.Sets/src/mage/cards/t/TeferisProtection.java @@ -28,11 +28,10 @@ package mage.cards.t; import java.util.UUID; +import mage.MageObject; import mage.abilities.Ability; -import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.ExileSpellEffect; -import mage.abilities.effects.common.NameACardEffect; import mage.abilities.effects.common.continuous.GainAbilityControllerEffect; import mage.abilities.effects.common.continuous.LifeTotalCantChangeControllerEffect; import mage.abilities.keyword.ProtectionAbility; @@ -41,9 +40,8 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Outcome; -import mage.filter.FilterObject; -import mage.filter.common.FilterControlledPermanent; -import mage.filter.predicate.mageobject.NamePredicate; +import mage.filter.FilterCard; +import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; @@ -58,7 +56,8 @@ public class TeferisProtection extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{W}"); // Until your next turn, your life total can't change, and you have protection from everything. All permanents you control phase out. (While they're phased out, they're treated as though they don't exist. They phase in before you untap during your untap step.) - this.getSpellAbility().addEffect(new LifeTotalCantChangeControllerEffect(Duration.UntilYourNextTurn)); + this.getSpellAbility().addEffect(new LifeTotalCantChangeControllerEffect(Duration.UntilYourNextTurn) + .setText("Until your next turn, your life total can't change")); this.getSpellAbility().addEffect(new TeferisProtectionEffect()); this.getSpellAbility().addEffect(new TeferisProtectionPhaseOutEffect()); @@ -78,9 +77,31 @@ public class TeferisProtection extends CardImpl { class TeferisProtectionEffect extends OneShotEffect { + /** + * 25.08.2017 The following rulings focus on the “protection from” keyword + * + * 25.08.2017 If a player has protection from everything, it means three + * things: 1) All damage that would be dealt to that player is prevented. 2) + * Auras can’t be attached to that player. 3) That player can’t be the + * target of spells or abilities. + * + * 25.08.2017 Nothing other than the specified events are prevented or + * illegal. An effect that doesn’t target you could still cause you to + * discard cards, for example. Creatures can still attack you while you have + * protection from everything, although combat damage that they would deal + * to you will be prevented. + * + * 25.08.2017 Gaining protection from everything causes a spell or ability + * on the stack to have an illegal target if it targets you. As a spell or + * ability tries to resolve, if all its targets are illegal, that spell or + * ability is countered and none of its effects happen, including effects + * unrelated to the target. If at least one target is still legal, the spell + * or ability does as much as it can to the remaining legal targets, and its + * other effects still happen. + */ public TeferisProtectionEffect() { super(Outcome.Protect); - staticText = "

You have protection from everything(You can't be targeted, dealt damage, or enchanted by anything.)"; + staticText = ", and you have protection from everything"; } public TeferisProtectionEffect(final TeferisProtectionEffect effect) { @@ -90,12 +111,8 @@ class TeferisProtectionEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - String cardName = (String) game.getState().getValue(source.getSourceId().toString() + NameACardEffect.INFO_KEY); if (controller != null) { - FilterObject filter = new FilterObject("the name [everything]"); - filter.add(new NamePredicate("everything")); - ContinuousEffect effect = new GainAbilityControllerEffect(new ProtectionAbility(filter), Duration.Custom); - game.addEffect(effect, source); + game.addEffect(new GainAbilityControllerEffect(new TeferisProtectionAbility(), Duration.UntilYourNextTurn), source); return true; } return false; @@ -107,9 +124,33 @@ class TeferisProtectionEffect extends OneShotEffect { } } -class TeferisProtectionPhaseOutEffect extends OneShotEffect { +class TeferisProtectionAbility extends ProtectionAbility { - private FilterControlledPermanent permanentsYouControl = new FilterControlledPermanent("all permanents you control"); + public TeferisProtectionAbility() { + super(new FilterCard("everything")); + } + + public TeferisProtectionAbility(final TeferisProtectionAbility ability) { + super(ability); + } + + @Override + public TeferisProtectionAbility copy() { + return new TeferisProtectionAbility(this); + } + + @Override + public String getRule() { + return "Protection from everything"; + } + + @Override + public boolean canTarget(MageObject source, Game game) { + return false; + } +} + +class TeferisProtectionPhaseOutEffect extends OneShotEffect { public TeferisProtectionPhaseOutEffect() { super(Outcome.Benefit); @@ -129,7 +170,7 @@ class TeferisProtectionPhaseOutEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { - for (Permanent permanent : game.getBattlefield().getActivePermanents(permanentsYouControl, controller.getId(), game)) { + for (Permanent permanent : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_CONTROLLED_PERMANENT, controller.getId(), game)) { permanent.phaseOut(game); } return true; diff --git a/Mage/src/main/java/mage/filter/StaticFilters.java b/Mage/src/main/java/mage/filter/StaticFilters.java index 6cfc22b324c..8638ff9ddd1 100644 --- a/Mage/src/main/java/mage/filter/StaticFilters.java +++ b/Mage/src/main/java/mage/filter/StaticFilters.java @@ -23,7 +23,6 @@ import mage.filter.predicate.permanent.TokenPredicate; */ public final class StaticFilters { - public static final FilterSpiritOrArcaneCard SPIRIT_OR_ARCANE_CARD = new FilterSpiritOrArcaneCard(); public static final FilterArtifactOrEnchantmentPermanent ARTIFACT_OR_ENCHANTMENT_PERMANENT = new FilterArtifactOrEnchantmentPermanent(); public static final FilterEnchantmentPermanent FILTER_ENCHANTMENT_PERMANENT = new FilterEnchantmentPermanent(); @@ -37,6 +36,8 @@ public final class StaticFilters { public static final FilterPermanent FILTER_PERMANENT_ARTIFACT_OR_CREATURE = new FilterPermanent("artifact or creature"); public static final FilterPermanent FILTER_PERMANENT_ARTIFACT_CREATURE_OR_ENCHANTMENT = new FilterPermanent("artifact, creature, or enchantment"); public static final FilterPermanent FILTER_PERMANENT_ARTIFACT_CREATURE_ENCHANTMENT_OR_LAND = new FilterPermanent("artifact, creature, enchantment, or land"); + + public static final FilterControlledPermanent FILTER_CONTROLLED_PERMANENT = new FilterControlledPermanent(); public static final FilterControlledPermanent FILTER_CONTROLLED_PERMANENT_ARTIFACT = new FilterControlledArtifactPermanent(); public static final FilterControlledPermanent FILTER_CONTROLLED_PERMANENT_ARTIFACT_OR_CREATURE = new FilterControlledPermanent("artifact or creature you control"); @@ -67,8 +68,6 @@ public final class StaticFilters { public static final FilterPermanent FILTER_ATTACKING_CREATURES = new FilterCreaturePermanent("attacking creatures"); - - public static final FilterPermanent FILTER_AURA = new FilterPermanent(); public static final FilterPermanent FILTER_EQUIPMENT = new FilterPermanent(); public static final FilterPermanent FILTER_FORTIFICATION = new FilterPermanent(); @@ -91,7 +90,6 @@ public final class StaticFilters { FILTER_CONTROLLED_PERMANENT_NON_LAND.add( Predicates.not(new CardTypePredicate(CardType.LAND))); - FILTER_CREATURE_TOKENS.add(new TokenPredicate()); FILTER_ATTACKING_CREATURES.add(new AttackingPredicate()); diff --git a/Mage/src/main/java/mage/players/PlayerImpl.java b/Mage/src/main/java/mage/players/PlayerImpl.java index 5fba8287f2d..412d99bb309 100644 --- a/Mage/src/main/java/mage/players/PlayerImpl.java +++ b/Mage/src/main/java/mage/players/PlayerImpl.java @@ -27,6 +27,10 @@ */ package mage.players; +import java.io.Serializable; +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.Map.Entry; import mage.ConditionalMana; import mage.MageObject; import mage.Mana; @@ -87,11 +91,6 @@ import mage.util.GameLog; import mage.util.RandomUtil; import org.apache.log4j.Logger; -import java.io.Serializable; -import java.text.SimpleDateFormat; -import java.util.*; -import java.util.Map.Entry; - public abstract class PlayerImpl implements Player, Serializable { private static final Logger logger = Logger.getLogger(PlayerImpl.class); @@ -1770,51 +1769,59 @@ public abstract class PlayerImpl implements Player, Serializable { @SuppressWarnings({"null", "ConstantConditions"}) private int doDamage(int damage, UUID sourceId, Game game, boolean combatDamage, boolean preventable, List appliedEffects) { - if (damage > 0 && canDamage(game.getObject(sourceId), game)) { - GameEvent event = new DamagePlayerEvent(playerId, sourceId, playerId, damage, preventable, combatDamage); - event.setAppliedEffects(appliedEffects); - if (!game.replaceEvent(event)) { - int actualDamage = event.getAmount(); - if (actualDamage > 0) { - UUID sourceControllerId = null; - Abilities sourceAbilities = null; - MageObject source = game.getPermanentOrLKIBattlefield(sourceId); - if (source == null) { - StackObject stackObject = game.getStack().getStackObject(sourceId); - if (stackObject != null) { - source = stackObject.getStackAbility().getSourceObject(game); + if (damage > 0) { + if (canDamage(game.getObject(sourceId), game)) { + GameEvent event = new DamagePlayerEvent(playerId, sourceId, playerId, damage, preventable, combatDamage); + event.setAppliedEffects(appliedEffects); + if (!game.replaceEvent(event)) { + int actualDamage = event.getAmount(); + if (actualDamage > 0) { + UUID sourceControllerId = null; + Abilities sourceAbilities = null; + MageObject source = game.getPermanentOrLKIBattlefield(sourceId); + if (source == null) { + StackObject stackObject = game.getStack().getStackObject(sourceId); + if (stackObject != null) { + source = stackObject.getStackAbility().getSourceObject(game); + } else { + source = game.getObject(sourceId); + } + if (source instanceof Spell) { + sourceAbilities = ((Spell) source).getAbilities(game); + sourceControllerId = ((Spell) source).getControllerId(); + } else if (source instanceof Card) { + sourceAbilities = ((Card) source).getAbilities(game); + sourceControllerId = ((Card) source).getOwnerId(); + } else if (source instanceof CommandObject) { + sourceControllerId = ((CommandObject) source).getControllerId(); + sourceAbilities = ((CommandObject) source).getAbilities(); + } } else { - source = game.getObject(sourceId); + sourceAbilities = ((Permanent) source).getAbilities(game); + sourceControllerId = ((Permanent) source).getControllerId(); } - if (source instanceof Spell) { - sourceAbilities = ((Spell) source).getAbilities(game); - sourceControllerId = ((Spell) source).getControllerId(); - } else if (source instanceof Card) { - sourceAbilities = ((Card) source).getAbilities(game); - sourceControllerId = ((Card) source).getOwnerId(); - } else if (source instanceof CommandObject) { - sourceControllerId = ((CommandObject) source).getControllerId(); - sourceAbilities = ((CommandObject) source).getAbilities(); + if (sourceAbilities != null && sourceAbilities.containsKey(InfectAbility.getInstance().getId())) { + addCounters(CounterType.POISON.createInstance(actualDamage), game); + } else { + GameEvent damageToLifeLossEvent = new GameEvent(EventType.DAMAGE_CAUSES_LIFE_LOSS, playerId, sourceId, playerId, actualDamage, combatDamage); + if (!game.replaceEvent(damageToLifeLossEvent)) { + this.loseLife(damageToLifeLossEvent.getAmount(), game, combatDamage); + } } - } else { - sourceAbilities = ((Permanent) source).getAbilities(game); - sourceControllerId = ((Permanent) source).getControllerId(); - } - if (sourceAbilities != null && sourceAbilities.containsKey(InfectAbility.getInstance().getId())) { - addCounters(CounterType.POISON.createInstance(actualDamage), game); - } else { - GameEvent damageToLifeLossEvent = new GameEvent(EventType.DAMAGE_CAUSES_LIFE_LOSS, playerId, sourceId, playerId, actualDamage, combatDamage); - if (!game.replaceEvent(damageToLifeLossEvent)) { - this.loseLife(damageToLifeLossEvent.getAmount(), game, combatDamage); + if (sourceAbilities != null && sourceAbilities.containsKey(LifelinkAbility.getInstance().getId())) { + Player player = game.getPlayer(sourceControllerId); + player.gainLife(actualDamage, game); } + game.fireEvent(new DamagedPlayerEvent(playerId, sourceId, playerId, actualDamage, combatDamage)); + return actualDamage; } - if (sourceAbilities != null && sourceAbilities.containsKey(LifelinkAbility.getInstance().getId())) { - Player player = game.getPlayer(sourceControllerId); - player.gainLife(actualDamage, game); - } - game.fireEvent(new DamagedPlayerEvent(playerId, sourceId, playerId, actualDamage, combatDamage)); - return actualDamage; } + } else { + MageObject sourceObject = game.getObject(sourceId); + game.informPlayers(damage + " damage " + + (sourceObject == null ? "" : "from " + sourceObject.getLogName()) + + "to " + getLogName() + + (damage > 1 ? " were" : "was") + " prevented because of protection."); } } return 0;