From b583b61c72a2c5cfd55c245a5929d3a5d80765a5 Mon Sep 17 00:00:00 2001 From: Plopman Date: Wed, 9 Oct 2013 22:28:15 +0200 Subject: [PATCH 1/3] Added Fading ability --- .../mage/abilities/keyword/FadingAbility.java | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 Mage/src/mage/abilities/keyword/FadingAbility.java diff --git a/Mage/src/mage/abilities/keyword/FadingAbility.java b/Mage/src/mage/abilities/keyword/FadingAbility.java new file mode 100644 index 00000000000..4358a088fa4 --- /dev/null +++ b/Mage/src/mage/abilities/keyword/FadingAbility.java @@ -0,0 +1,89 @@ +package mage.abilities.keyword; + +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.EntersBattlefieldAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.cards.Card; +import mage.constants.Outcome; +import mage.constants.TargetController; +import mage.counters.CounterType; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/* + * 702.31. Fading + * + * 702.31a Fading is a keyword that represents two abilities. “Fading N” means “This permanent enters the battlefield with N fade counters on it” and “At the beginning of your upkeep, remove a fade counter from this permanent. If you can’t, sacrifice the permanent.” + * + */ + +public class FadingAbility extends EntersBattlefieldAbility { + + + private String ruleText; + + public FadingAbility(int fadeCounter, Card card) { + super(new AddCountersSourceEffect(CounterType.FADE.createInstance(fadeCounter)), "with"); + Ability ability = new BeginningOfUpkeepTriggeredAbility(new FadingEffect(), TargetController.YOU, false); + ability.setRuleVisible(false); + card.addAbility(ability); + StringBuilder sb = new StringBuilder("Fading "); + sb.append(fadeCounter); + sb.append(" (This permanent enters the battlefield with ") + .append(fadeCounter) + .append(" fade counters on it. ") + .append(" At the beginning of your upkeep, remove a fade counter from this permanent. If you can’t, sacrifice the permanent.") + .append(")"); + ruleText = sb.toString(); + } + + public FadingAbility(final FadingAbility ability) { + super(ability); + this.ruleText = ability.ruleText; + } + + @Override + public EntersBattlefieldAbility copy() { + return new FadingAbility(this); + } + + @Override + public String getRule() { + return ruleText; + } +} +class FadingEffect extends OneShotEffect { + FadingEffect() { + super(Outcome.Sacrifice); + staticText = "remove a fade counter from this permanent. If you can’t, sacrifice the permanent"; + } + + FadingEffect(final FadingEffect effect) { + super(effect); + } + + + @Override + public boolean apply(Game game, Ability source) { + Permanent p = game.getPermanent(source.getSourceId()); + if (p != null) { + int amount = p.getCounters().getCount(CounterType.FADE); + if (amount > 0) { + p.removeCounters(CounterType.FADE.createInstance(), game); + } + else + { + p.sacrifice(source.getSourceId(), game); + } + return true; + } + return false; + } + + @Override + public FadingEffect copy() { + return new FadingEffect(this); + } +} \ No newline at end of file From 607bf3ce42b351ddda3bdeaaa340c472c86f6a37 Mon Sep 17 00:00:00 2001 From: Plopman Date: Wed, 9 Oct 2013 22:29:19 +0200 Subject: [PATCH 2/3] Added Duplicant and Tangle Wire --- .../src/mage/sets/mirrodin/Duplicant.java | 185 ++++++++++++++++++ .../src/mage/sets/nemesis/TangleWire.java | 127 ++++++++++++ 2 files changed, 312 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/mirrodin/Duplicant.java create mode 100644 Mage.Sets/src/mage/sets/nemesis/TangleWire.java diff --git a/Mage.Sets/src/mage/sets/mirrodin/Duplicant.java b/Mage.Sets/src/mage/sets/mirrodin/Duplicant.java new file mode 100644 index 00000000000..dd14faab340 --- /dev/null +++ b/Mage.Sets/src/mage/sets/mirrodin/Duplicant.java @@ -0,0 +1,185 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.mirrodin; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.OneShotEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Layer; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.SubLayer; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.permanent.TokenPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author Plopman + */ +public class Duplicant extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nontoken creature"); + static { + filter.add(Predicates.not(new TokenPredicate())); + } + public Duplicant(UUID ownerId) { + super(ownerId, 165, "Duplicant", Rarity.RARE, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{6}"); + this.expansionSetCode = "MRD"; + this.subtype.add("Shapeshifter"); + + this.power = new MageInt(2); + this.toughness = new MageInt(4); + + // Imprint - When Duplicant enters the battlefield, you may exile target nontoken creature. + Ability ability = new EntersBattlefieldTriggeredAbility(new ExileTargetEffect(), true, "Imprint - "); + ability.addTarget(new TargetCreaturePermanent(filter)); + this.addAbility(ability); + // As long as the exiled card is a creature card, Duplicant has that card's power, toughness, and creature types. It's still a Shapeshifter. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new DuplicantContinuousEffect())); + } + + public Duplicant(final Duplicant card) { + super(card); + } + + @Override + public Duplicant copy() { + return new Duplicant(this); + } +} +class ExileTargetEffect extends OneShotEffect { + + + public ExileTargetEffect() { + super(Outcome.Exile); + } + + public ExileTargetEffect(final ExileTargetEffect effect) { + super(effect); + } + + @Override + public ExileTargetEffect copy() { + return new ExileTargetEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(targetPointer.getFirst(game, source)); + Permanent sourcePermananent = game.getPermanent(source.getSourceId()); + if (permanent != null) { + if(sourcePermananent != null){ + sourcePermananent.imprint(permanent.getId(), game); + sourcePermananent.addInfo("imprint", new StringBuilder("[Imprinted card - ").append(permanent.getName()).append("]").toString()); + } + return permanent.moveToExile(null, null, source.getSourceId(), game); + } + + return false; + } + + @Override + public String getText(Mode mode) { + return "you may exile target nontoken creature"; + } +} + + +class DuplicantContinuousEffect extends ContinuousEffectImpl { + + public DuplicantContinuousEffect() { + super(Duration.WhileOnBattlefield, Outcome.BoostCreature); + staticText = "As long as the exiled card is a creature card, Duplicant has that card's power, toughness, and creature types. It's still a Shapeshifter"; + } + + public DuplicantContinuousEffect(final DuplicantContinuousEffect effect) { + super(effect); + } + + @Override + public DuplicantContinuousEffect copy() { + return new DuplicantContinuousEffect(this); + } + + @Override + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + Permanent permanent = game.getPermanent(source.getSourceId()); + if (permanent != null) { + if(permanent.getImprinted().size() > 0){ + Card card = game.getCard(permanent.getImprinted().get(0)); + if(card != null && card.getCardType().contains(CardType.CREATURE)) + { + switch (layer) { + case TypeChangingEffects_4: + if (sublayer == SubLayer.NA) { + permanent.getSubtype().addAll(card.getSubtype()); + } + + break; + case PTChangingEffects_7: + if (sublayer == SubLayer.SetPT_7b) { + permanent.getPower().setValue(card.getPower().getValue()); + permanent.getToughness().setValue(card.getToughness().getValue()); + + } + } + return true; + + + } + } + + } + return false; + } + + @Override + public boolean apply(Game game, Ability source) { + return false; + } + + @Override + public boolean hasLayer(Layer layer) { + return layer == Layer.PTChangingEffects_7 || layer == Layer.TypeChangingEffects_4; + } + +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/nemesis/TangleWire.java b/Mage.Sets/src/mage/sets/nemesis/TangleWire.java new file mode 100644 index 00000000000..7942176cb76 --- /dev/null +++ b/Mage.Sets/src/mage/sets/nemesis/TangleWire.java @@ -0,0 +1,127 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.nemesis; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.FadingAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.permanent.TappedPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.Target; +import mage.target.common.TargetControlledPermanent; + +/** + * + * @author Plopman + */ +public class TangleWire extends CardImpl { + + public TangleWire(UUID ownerId) { + super(ownerId, 139, "Tangle Wire", Rarity.RARE, new CardType[]{CardType.ARTIFACT}, "{3}"); + this.expansionSetCode = "NMS"; + + // Fading 4 + this.addAbility(new FadingAbility(4, this)); + // At the beginning of each player's upkeep, that player taps an untapped artifact, creature, or land he or she controls for each fade counter on Tangle Wire. + this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new TangleWireEffect(), TargetController.ANY, false, true)); + } + + public TangleWire(final TangleWire card) { + super(card); + } + + @Override + public TangleWire copy() { + return new TangleWire(this); + } +} +class TangleWireEffect extends OneShotEffect { + + private static final FilterControlledPermanent filter = new FilterControlledPermanent("untapped artifact, creature, or land he or she controls"); + static{ + filter.add(Predicates.not(new TappedPredicate())); + } + + TangleWireEffect() { + super(Outcome.Sacrifice); + staticText = "that player taps an untapped artifact, creature, or land he or she controls for each fade counter on Tangle Wire"; + } + + TangleWireEffect(final TangleWireEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(targetPointer.getFirst(game, source)); + Permanent permanent = game.getPermanent(source.getSourceId()); + if (player == null || permanent == null) { + return false; + } + + int targetCount = game.getBattlefield().countAll(filter, player.getId(), game); + int counterCount = permanent.getCounters().getCount(CounterType.FADE); + int amount = Math.min(counterCount, targetCount); + + Target target = new TargetControlledPermanent(amount, amount, filter, false); + target.setRequired(true); + target.setNotTarget(true); + + if (player.chooseTarget(Outcome.Tap, target, source, game)) { + boolean abilityApplied = false; + + for (UUID uuid : target.getTargets()) { + Permanent selectedPermanent = game.getPermanent(uuid); + if ( selectedPermanent != null ) { + abilityApplied |= selectedPermanent.tap(game); + } + } + + return abilityApplied; + } + return false; + } + + @Override + public TangleWireEffect copy() { + return new TangleWireEffect(this); + } +} \ No newline at end of file From 0579ddc1bddefab455e6d57c54ab4669ce798875 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Thu, 10 Oct 2013 00:01:20 +0200 Subject: [PATCH 3/3] Fixed Spear of Heliod, Dunerider Outlaw, Whirling Dervish, Reciprocate, Wicked Akuba, Giltspire Avenger only counting damage done, if the same permanent had done the damage (i.e. it cant be selected if the creature was exiled with Cloudshift). --- .../sets/championsofkamigawa/Reciprocate.java | 13 ++++--- .../sets/championsofkamigawa/WickedAkuba.java | 11 +++--- .../mage/sets/conflux/GiltspireAvenger.java | 13 ++++--- .../common/DealtDamageToAnOpponent.java | 4 +-- .../DamagedPlayerThisTurnPredicate.java | 16 ++++----- .../common/PlayerDamagedBySourceWatcher.java | 36 ++++++++++++------- 6 files changed, 51 insertions(+), 42 deletions(-) diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/Reciprocate.java b/Mage.Sets/src/mage/sets/championsofkamigawa/Reciprocate.java index c35c223381d..3bc51cb49e6 100644 --- a/Mage.Sets/src/mage/sets/championsofkamigawa/Reciprocate.java +++ b/Mage.Sets/src/mage/sets/championsofkamigawa/Reciprocate.java @@ -31,13 +31,12 @@ package mage.sets.championsofkamigawa; import java.util.HashSet; import java.util.Set; import java.util.UUID; - -import mage.constants.CardType; -import mage.constants.Rarity; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.effects.common.ExileTargetEffect; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.game.permanent.Permanent; @@ -46,7 +45,7 @@ import mage.target.common.TargetCreaturePermanent; import mage.watchers.common.PlayerDamagedBySourceWatcher; /** - * @author LevelX + * @author LevelX2 */ public class Reciprocate extends CardImpl { @@ -84,7 +83,7 @@ class ReciprocateTarget> extends TargetPerm @Override public boolean canTarget(UUID id, Ability source, Game game) { PlayerDamagedBySourceWatcher watcher = (PlayerDamagedBySourceWatcher) game.getState().getWatchers().get("PlayerDamagedBySource",source.getControllerId()); - if (watcher != null && watcher.damageSources.contains(id)) { + if (watcher != null && watcher.hasSourceDoneDamage(id, game)) { return super.canTarget(id, source, game); } return false; @@ -97,7 +96,7 @@ class ReciprocateTarget> extends TargetPerm PlayerDamagedBySourceWatcher watcher = (PlayerDamagedBySourceWatcher) game.getState().getWatchers().get("PlayerDamagedBySource", sourceControllerId); for (UUID targetId : availablePossibleTargets) { Permanent permanent = game.getPermanent(targetId); - if(permanent != null && watcher != null && watcher.damageSources.contains(targetId)){ + if(permanent != null && watcher != null && watcher.hasSourceDoneDamage(targetId, game)){ possibleTargets.add(targetId); } } @@ -115,7 +114,7 @@ class ReciprocateTarget> extends TargetPerm PlayerDamagedBySourceWatcher watcher = (PlayerDamagedBySourceWatcher) game.getState().getWatchers().get("PlayerDamagedBySource", sourceControllerId); for (Permanent permanent: game.getBattlefield().getActivePermanents(filter, sourceControllerId, sourceId, game)) { if (!targets.containsKey(permanent.getId()) && permanent.canBeTargetedBy(targetSource, sourceControllerId, game) - && watcher != null && watcher.damageSources.contains(permanent.getId())) { + && watcher != null && watcher.hasSourceDoneDamage(permanent.getId(), game)) { count++; if (count >= remainingTargets) { return true; diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/WickedAkuba.java b/Mage.Sets/src/mage/sets/championsofkamigawa/WickedAkuba.java index 828d69385ed..c95d6be99be 100644 --- a/Mage.Sets/src/mage/sets/championsofkamigawa/WickedAkuba.java +++ b/Mage.Sets/src/mage/sets/championsofkamigawa/WickedAkuba.java @@ -28,17 +28,16 @@ package mage.sets.championsofkamigawa; import java.util.UUID; - -import mage.constants.CardType; -import mage.constants.Rarity; -import mage.constants.Zone; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.ColoredManaCost; import mage.abilities.effects.common.LoseLifeTargetEffect; import mage.cards.CardImpl; +import mage.constants.CardType; import mage.constants.ColoredManaSymbol; +import mage.constants.Rarity; +import mage.constants.Zone; import mage.filter.FilterPlayer; import mage.filter.predicate.ObjectSourcePlayer; import mage.filter.predicate.ObjectSourcePlayerPredicate; @@ -89,8 +88,8 @@ class WickedAkubaPredicate implements ObjectSourcePlayerPredicate input, Game game) { PlayerDamagedBySourceWatcher watcher = (PlayerDamagedBySourceWatcher) game.getState().getWatchers().get("PlayerDamagedBySource", input.getObject().getId()); - if (watcher != null && watcher.damageSources.contains(input.getSourceId())) { - return true; + if (watcher != null) { + return watcher.hasSourceDoneDamage(input.getSourceId(), game); } return false; diff --git a/Mage.Sets/src/mage/sets/conflux/GiltspireAvenger.java b/Mage.Sets/src/mage/sets/conflux/GiltspireAvenger.java index 6979300bda0..61bc2cbe6a0 100644 --- a/Mage.Sets/src/mage/sets/conflux/GiltspireAvenger.java +++ b/Mage.Sets/src/mage/sets/conflux/GiltspireAvenger.java @@ -30,9 +30,6 @@ package mage.sets.conflux; import java.util.HashSet; import java.util.Set; import java.util.UUID; -import mage.constants.CardType; -import mage.constants.Rarity; -import mage.constants.Zone; import mage.MageInt; import mage.MageObject; import mage.abilities.Ability; @@ -41,6 +38,9 @@ import mage.abilities.costs.common.TapSourceCost; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.keyword.ExaltedAbility; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.game.permanent.Permanent; @@ -48,7 +48,6 @@ import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.watchers.common.PlayerDamagedBySourceWatcher; - /** * * @author BetaSteward_at_googlemail.com @@ -103,7 +102,7 @@ class GiltspireAvengerTarget> extends Targe @Override public boolean canTarget(UUID id, Ability source, Game game) { PlayerDamagedBySourceWatcher watcher = (PlayerDamagedBySourceWatcher) game.getState().getWatchers().get("PlayerDamagedBySource",source.getControllerId()); - if (watcher != null && watcher.damageSources.contains(id)) { + if (watcher != null && watcher.hasSourceDoneDamage(id, game)) { return super.canTarget(id, source, game); } return false; @@ -116,7 +115,7 @@ class GiltspireAvengerTarget> extends Targe PlayerDamagedBySourceWatcher watcher = (PlayerDamagedBySourceWatcher) game.getState().getWatchers().get("PlayerDamagedBySource", sourceControllerId); for (UUID targetId : availablePossibleTargets) { Permanent permanent = game.getPermanent(targetId); - if(permanent != null && watcher != null && watcher.damageSources.contains(targetId)){ + if(permanent != null && watcher != null && watcher.hasSourceDoneDamage(targetId, game)){ possibleTargets.add(targetId); } } @@ -134,7 +133,7 @@ class GiltspireAvengerTarget> extends Targe PlayerDamagedBySourceWatcher watcher = (PlayerDamagedBySourceWatcher) game.getState().getWatchers().get("PlayerDamagedBySource", sourceControllerId); for (Permanent permanent: game.getBattlefield().getActivePermanents(filter, sourceControllerId, sourceId, game)) { if (!targets.containsKey(permanent.getId()) && permanent.canBeTargetedBy(targetSource, sourceControllerId, game) - && watcher != null && watcher.damageSources.contains(permanent.getId())) { + && watcher != null && watcher.hasSourceDoneDamage(permanent.getId(), game)) { count++; if (count >= remainingTargets) { return true; diff --git a/Mage/src/mage/abilities/condition/common/DealtDamageToAnOpponent.java b/Mage/src/mage/abilities/condition/common/DealtDamageToAnOpponent.java index c185837e206..192d0cf5715 100644 --- a/Mage/src/mage/abilities/condition/common/DealtDamageToAnOpponent.java +++ b/Mage/src/mage/abilities/condition/common/DealtDamageToAnOpponent.java @@ -45,8 +45,8 @@ public class DealtDamageToAnOpponent implements Condition { public boolean apply(Game game, Ability source) { for (UUID opponentId: game.getOpponents(source.getControllerId())) { PlayerDamagedBySourceWatcher watcher = (PlayerDamagedBySourceWatcher) game.getState().getWatchers().get("PlayerDamagedBySource", opponentId); - if (watcher != null && watcher.damageSources.contains(source.getSourceId())) { - return true; + if (watcher != null) { + return watcher.hasSourceDoneDamage(source.getSourceId(), game); } } return false; diff --git a/Mage/src/mage/filter/predicate/permanent/DamagedPlayerThisTurnPredicate.java b/Mage/src/mage/filter/predicate/permanent/DamagedPlayerThisTurnPredicate.java index fcb90b1a029..6e85fa29ba6 100644 --- a/Mage/src/mage/filter/predicate/permanent/DamagedPlayerThisTurnPredicate.java +++ b/Mage/src/mage/filter/predicate/permanent/DamagedPlayerThisTurnPredicate.java @@ -57,15 +57,15 @@ public class DamagedPlayerThisTurnPredicate implements ObjectPlayerPredicate { - public List damageSources = new ArrayList(); + private Set damageSourceIds = new HashSet(); public PlayerDamagedBySourceWatcher(UUID playerId) { super("PlayerDamagedBySource", WatcherScope.PLAYER); - setControllerId(playerId); + setControllerId(playerId); } public PlayerDamagedBySourceWatcher(final PlayerDamagedBySourceWatcher watcher) { super(watcher); - this.damageSources.addAll(watcher.damageSources); + this.damageSourceIds.addAll(watcher.damageSourceIds); } @Override @@ -64,15 +64,27 @@ public class PlayerDamagedBySourceWatcher extends WatcherImpl