diff --git a/Mage.Sets/src/mage/sets/innistrad/BackFromTheBrink.java b/Mage.Sets/src/mage/sets/innistrad/BackFromTheBrink.java index af2c366afb8..5738cbd5271 100644 --- a/Mage.Sets/src/mage/sets/innistrad/BackFromTheBrink.java +++ b/Mage.Sets/src/mage/sets/innistrad/BackFromTheBrink.java @@ -122,7 +122,7 @@ class BackFromTheBrinkCost extends CostImpl { @Override public boolean canPay(UUID sourceId, UUID controllerId, Game game) { - return targets.canChoose(controllerId, controllerId, game); + return targets.canChoose(controllerId, game); } @Override diff --git a/Mage.Sets/src/mage/sets/innistrad/CivilizedScholar.java b/Mage.Sets/src/mage/sets/innistrad/CivilizedScholar.java index 96e03c4944a..7f78f666f0c 100644 --- a/Mage.Sets/src/mage/sets/innistrad/CivilizedScholar.java +++ b/Mage.Sets/src/mage/sets/innistrad/CivilizedScholar.java @@ -44,6 +44,8 @@ import mage.players.Player; import mage.target.common.TargetDiscard; import java.util.UUID; +import mage.game.events.GameEvent; +import mage.watchers.WatcherImpl; /** * @author nantuko @@ -67,7 +69,7 @@ public class CivilizedScholar extends CardImpl { this.addAbility(new SimpleActivatedAbility(Constants.Zone.BATTLEFIELD, new CivilizedScholarEffect(), new TapSourceCost())); this.addAbility(new TransformAbility()); -// this.addWatcher(new HomicidalBrute.HomicidalBruteWatcher()); + this.addWatcher(new HomicidalBruteWatcher()); } public CivilizedScholar(final CivilizedScholar card) { @@ -80,6 +82,31 @@ public class CivilizedScholar extends CardImpl { } } +class HomicidalBruteWatcher extends WatcherImpl { + + public HomicidalBruteWatcher() { + super("HomicidalBruteAttacked", Constants.WatcherScope.CARD); + } + + public HomicidalBruteWatcher(final HomicidalBruteWatcher watcher) { + super(watcher); + } + + @Override + public HomicidalBruteWatcher copy() { + return new HomicidalBruteWatcher(this); + } + + @Override + public void watch(GameEvent event, Game game) { + if (condition == true) + return; + if (event.getType() == GameEvent.EventType.ATTACKER_DECLARED && event.getSourceId().equals(sourceId)) { + condition = true; + } + } +} + class CivilizedScholarEffect extends OneShotEffect { public CivilizedScholarEffect() { diff --git a/Mage.Sets/src/mage/sets/innistrad/HomicidalBrute.java b/Mage.Sets/src/mage/sets/innistrad/HomicidalBrute.java index c98c80d526e..240a073df1f 100644 --- a/Mage.Sets/src/mage/sets/innistrad/HomicidalBrute.java +++ b/Mage.Sets/src/mage/sets/innistrad/HomicidalBrute.java @@ -65,7 +65,6 @@ public class HomicidalBrute extends CardImpl { // At the beginning of your end step, if Homicidal Brute didn't attack this turn, tap Homicidal Brute, then transform it. this.addAbility(new HomicidalBruteTriggeredAbility()); - this.addWatcher(new HomicidalBruteWatcher()); } public HomicidalBrute(final HomicidalBrute card) { @@ -79,31 +78,6 @@ public class HomicidalBrute extends CardImpl { } -class HomicidalBruteWatcher extends WatcherImpl { - - public HomicidalBruteWatcher() { - super("HomicidalBruteAttacked", WatcherScope.CARD); - } - - public HomicidalBruteWatcher(final HomicidalBruteWatcher watcher) { - super(watcher); - } - - @Override - public HomicidalBruteWatcher copy() { - return new HomicidalBruteWatcher(this); - } - - @Override - public void watch(GameEvent event, Game game) { - if (condition == true) - return; - if (event.getType() == GameEvent.EventType.ATTACKER_DECLARED && event.getSourceId().equals(sourceId)) { - condition = true; - } - } -} - class HomicidalBruteTriggeredAbility extends TriggeredAbilityImpl { public HomicidalBruteTriggeredAbility() { @@ -124,7 +98,7 @@ class HomicidalBruteTriggeredAbility extends TriggeredAbilityImpl { this.getSpellAbility().addEffect(new AttachEffect(Outcome.Detriment)); Ability ability = new EnchantAbility(auraTarget.getTargetName()); this.addAbility(ability); - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new NecroticPlagueEffect())); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new NecroticPlagueEffect(this.objectId))); } @@ -81,21 +82,44 @@ public class NecroticPlague extends CardImpl { super(card); } + @Override + public void assignNewId() { + super.assignNewId(); + updateSource(); + } + @Override public NecroticPlague copy() { return new NecroticPlague(this); } + + private void updateSource() { + for (Ability ability: abilities) { + for (Effect effect: ability.getEffects()) { + if (effect instanceof NecroticPlagueEffect) { + ((NecroticPlagueEffect)effect).updateSource(objectId); + } + } + } + } } class NecroticPlagueEffect extends ContinuousEffectImpl { - public NecroticPlagueEffect() { + private Ability ability1; + private Ability ability2; + + public NecroticPlagueEffect(UUID cardId) { super(Duration.WhileOnBattlefield, Outcome.Detriment); + ability1 = new OnEventTriggeredAbility(EventType.UPKEEP_STEP_PRE, "beginning of your upkeep", new SacrificeSourceEffect()); + ability2 = new DiesTriggeredAbility(new NecroticPlagueEffect2(cardId), false); staticText = "Enchanted creature has \"At the beginning of your upkeep, sacrifice this creature.\" When enchanted creature is put into a graveyard, its controller chooses target creature one of his or her opponents controls. Return {this} from its owner's graveyard to the battlefield attached to that creature."; } public NecroticPlagueEffect(final NecroticPlagueEffect effect) { super(effect); + this.ability1 = effect.ability1.copy(); + this.ability2 = effect.ability2.copy(); } @Override @@ -112,8 +136,8 @@ class NecroticPlagueEffect extends ContinuousEffectImpl { switch (layer) { case AbilityAddingRemovingEffects_6: if (sublayer == SubLayer.NA) { - creature.addAbility(new OnEventTriggeredAbility(EventType.UPKEEP_STEP_PRE, "beginning of your upkeep", new SacrificeSourceEffect()), game); - creature.addAbility(new DiesTriggeredAbility(new NecroticPlagueEffect2(source.getSourceId()), false), game); + creature.addAbility(ability1, game); + creature.addAbility(ability2, game); } break; } @@ -123,6 +147,14 @@ class NecroticPlagueEffect extends ContinuousEffectImpl { return false; } + public void updateSource(UUID id) { + for (Effect effect: ability2.getEffects()) { + if (effect instanceof NecroticPlagueEffect2) { + ((NecroticPlagueEffect2)effect).updateSource(id); + } + } + } + @Override public boolean apply(Game game, Ability source) { return false; @@ -137,14 +169,14 @@ class NecroticPlagueEffect extends ContinuousEffectImpl { class NecroticPlagueEffect2 extends OneShotEffect { + private UUID cardId; + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature an opponent controls"); static { filter.setTargetController(TargetController.OPPONENT); } - protected UUID cardId; - public NecroticPlagueEffect2(UUID cardId) { super(Outcome.PutCardInPlay); this.cardId = cardId; @@ -177,6 +209,10 @@ class NecroticPlagueEffect2 extends OneShotEffect { return false; } + public void updateSource(UUID id) { + this.cardId = id; + } + @Override public NecroticPlagueEffect2 copy() { return new NecroticPlagueEffect2(this); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/TestHomicidalBrute.java b/Mage.Tests/src/test/java/org/mage/test/cards/TestHomicidalBrute.java index 2e493b8fa32..59d26e14195 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/TestHomicidalBrute.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/TestHomicidalBrute.java @@ -12,15 +12,75 @@ public class TestHomicidalBrute extends CardTestPlayerBase { @Test public void testCard() { + removeAllCardsFromHand(playerA); + removeAllCardsFromLibrary(playerA); addCard(Constants.Zone.BATTLEFIELD, playerA, "Civilized Scholar"); + addCard(Constants.Zone.LIBRARY, playerA, "Sejiri Merfolk"); - setStopAt(2, Constants.PhaseStep.BEGIN_COMBAT); + activateAbility(1, Constants.PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Draw a card, then discard a card. "); + setStopAt(1, Constants.PhaseStep.BEGIN_COMBAT); execute(); assertLife(playerA, 20); assertLife(playerB, 20); assertPermanentCount(playerA, "Civilized Scholar", 0); assertPermanentCount(playerA, "Homicidal Brute", 1); + assertTapped("Homicidal Brute", false); } - + + @Test + public void testCardNegative() { + removeAllCardsFromHand(playerA); + removeAllCardsFromLibrary(playerA); + addCard(Constants.Zone.BATTLEFIELD, playerA, "Civilized Scholar"); + addCard(Constants.Zone.LIBRARY, playerA, "Lightning Bolt"); + + activateAbility(1, Constants.PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Draw a card, then discard a card. "); + setStopAt(1, Constants.PhaseStep.BEGIN_COMBAT); + execute(); + + assertLife(playerA, 20); + assertLife(playerB, 20); + assertPermanentCount(playerA, "Civilized Scholar", 1); + assertTapped("Civilized Scholar", true); + assertPermanentCount(playerA, "Homicidal Brute", 0); + } + + @Test + public void testCardTransform() { + removeAllCardsFromHand(playerA); + removeAllCardsFromLibrary(playerA); + addCard(Constants.Zone.BATTLEFIELD, playerA, "Civilized Scholar"); + addCard(Constants.Zone.LIBRARY, playerA, "Sejiri Merfolk"); + + activateAbility(1, Constants.PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Draw a card, then discard a card. "); + setStopAt(2, Constants.PhaseStep.UPKEEP); + execute(); + + assertLife(playerA, 20); + assertLife(playerB, 20); + assertPermanentCount(playerA, "Civilized Scholar", 1); + assertTapped("Civilized Scholar", true); + assertPermanentCount(playerA, "Homicidal Brute", 0); + } + + @Test + public void testCardNotTransform() { + removeAllCardsFromHand(playerA); + removeAllCardsFromLibrary(playerA); + addCard(Constants.Zone.BATTLEFIELD, playerA, "Civilized Scholar"); + addCard(Constants.Zone.LIBRARY, playerA, "Sejiri Merfolk", 2); + + activateAbility(3, Constants.PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Draw a card, then discard a card. "); + attack(3, playerA, "Homicidal Brute"); + setStopAt(4, Constants.PhaseStep.UPKEEP); + execute(); + + assertLife(playerA, 20); + assertLife(playerB, 15); + assertPermanentCount(playerA, "Civilized Scholar", 0); + assertPermanentCount(playerA, "Homicidal Brute", 1); + assertTapped("Homicidal Brute", true); + } + } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/TestNecroticPlague.java b/Mage.Tests/src/test/java/org/mage/test/cards/TestNecroticPlague.java new file mode 100644 index 00000000000..cd98225d21f --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/TestNecroticPlague.java @@ -0,0 +1,59 @@ +package org.mage.test.cards; + +import mage.Constants; +import org.junit.Ignore; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * also tests triggered abilities that switch from one permanent to another + * + * @author BetaSteward + * + */ +public class TestNecroticPlague extends CardTestPlayerBase { + + @Test + public void testCard1() { + addCard(Constants.Zone.BATTLEFIELD, playerA, "Swamp", 4); + addCard(Constants.Zone.HAND, playerA, "Necrotic Plague"); + addCard(Constants.Zone.BATTLEFIELD, playerB, "Sejiri Merfolk"); + + castSpell(1, Constants.PhaseStep.PRECOMBAT_MAIN, playerA, "Necrotic Plague", "Sejiri Merfolk"); + + setStopAt(2, Constants.PhaseStep.PRECOMBAT_MAIN); + execute(); + + assertLife(playerA, 20); + assertLife(playerB, 20); + assertPermanentCount(playerB, "Sejiri Merfolk", 0); + assertGraveyardCount(playerA, "Necrotic Plague", 1); + assertGraveyardCount(playerB, 1); + assertGraveyardCount(playerB, "Sejiri Merfolk", 1); + } + + @Test + public void testCard2() { + addCard(Constants.Zone.BATTLEFIELD, playerA, "Swamp", 4); + addCard(Constants.Zone.BATTLEFIELD, playerA, "Goblin Deathraiders"); + addCard(Constants.Zone.HAND, playerA, "Necrotic Plague"); + addCard(Constants.Zone.BATTLEFIELD, playerB, "Sejiri Merfolk"); + + castSpell(1, Constants.PhaseStep.PRECOMBAT_MAIN, playerA, "Necrotic Plague", "Sejiri Merfolk"); + + setStopAt(3, Constants.PhaseStep.PRECOMBAT_MAIN); + execute(); + + assertLife(playerA, 20); + assertLife(playerB, 20); + assertPermanentCount(playerA, "Goblin Deathraiders", 0); + assertPermanentCount(playerB, "Sejiri Merfolk", 0); + assertGraveyardCount(playerA, 2); + assertGraveyardCount(playerA, "Necrotic Plague", 1); + assertGraveyardCount(playerA, "Goblin Deathraiders", 1); + assertGraveyardCount(playerB, 1); + assertGraveyardCount(playerB, "Sejiri Merfolk", 1); + } + +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/TestTurnToFrog.java b/Mage.Tests/src/test/java/org/mage/test/cards/TestTurnToFrog.java new file mode 100644 index 00000000000..77f0e3906d2 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/TestTurnToFrog.java @@ -0,0 +1,61 @@ +package org.mage.test.cards; + +import mage.Constants; +import mage.counters.CounterType; +import mage.filter.Filter; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * also tests triggered abilities that are added to permanents + * + * @author BetaSteward + */ +public class TestTurnToFrog extends CardTestPlayerBase { + + @Test + public void testCard() { + addCard(Constants.Zone.BATTLEFIELD, playerA, "Mountain", 3); + addCard(Constants.Zone.BATTLEFIELD, playerA, "Forest", 1); + addCard(Constants.Zone.BATTLEFIELD, playerA, "Raging Ravine"); + addCard(Constants.Zone.BATTLEFIELD, playerB, "Island", 2); + addCard(Constants.Zone.HAND, playerB, "Turn to Frog"); + + activateAbility(1, Constants.PhaseStep.PRECOMBAT_MAIN, playerA, "{2}{R}{G}: until end of turn {this} becomes a 3/3 red and green Elemental creature with \"Whenever this creature attacks, put a +1/+1 counter on it.\" that's still a land. "); + castSpell(1, Constants.PhaseStep.PRECOMBAT_MAIN, playerB, "Turn to Frog", "Raging Ravine"); + attack(1, playerA, "Raging Ravine"); + + setStopAt(1, Constants.PhaseStep.END_COMBAT); + execute(); + + assertLife(playerA, 20); + assertLife(playerB, 19); + assertPowerToughness(playerA, "Raging Ravine", 1, 1, Filter.ComparisonScope.Any); + assertCounterCount("Raging Ravine", CounterType.P1P1, 0); + } + + @Test + public void testCard2() { + addCard(Constants.Zone.BATTLEFIELD, playerA, "Mountain", 3); + addCard(Constants.Zone.BATTLEFIELD, playerA, "Forest", 1); + addCard(Constants.Zone.BATTLEFIELD, playerA, "Raging Ravine"); + addCard(Constants.Zone.BATTLEFIELD, playerB, "Island", 2); + addCard(Constants.Zone.HAND, playerB, "Turn to Frog"); + + activateAbility(1, Constants.PhaseStep.PRECOMBAT_MAIN, playerA, "{2}{R}{G}: until end of turn {this} becomes a 3/3 red and green Elemental creature with \"Whenever this creature attacks, put a +1/+1 counter on it.\" that's still a land. "); + castSpell(1, Constants.PhaseStep.PRECOMBAT_MAIN, playerB, "Turn to Frog", "Raging Ravine"); + + activateAbility(3, Constants.PhaseStep.PRECOMBAT_MAIN, playerA, "{2}{R}{G}: until end of turn {this} becomes a 3/3 red and green Elemental creature with \"Whenever this creature attacks, put a +1/+1 counter on it.\" that's still a land. "); + attack(3, playerA, "Raging Ravine"); + + setStopAt(3, Constants.PhaseStep.END_COMBAT); + execute(); + + assertLife(playerA, 20); + assertLife(playerB, 16); + assertPowerToughness(playerA, "Raging Ravine", 4, 4, Filter.ComparisonScope.Any); + assertCounterCount("Raging Ravine", CounterType.P1P1, 1); + } + +} diff --git a/Mage.Tests/src/test/java/org/mage/test/serverside/TestPlayRandomGame.java b/Mage.Tests/src/test/java/org/mage/test/serverside/TestPlayRandomGame.java index d15c755a893..7f7df12e3f6 100644 --- a/Mage.Tests/src/test/java/org/mage/test/serverside/TestPlayRandomGame.java +++ b/Mage.Tests/src/test/java/org/mage/test/serverside/TestPlayRandomGame.java @@ -29,6 +29,7 @@ public class TestPlayRandomGame extends MageTestBase { private static List colorChoices = Arrays.asList("bu", "bg", "br", "bw", "ug", "ur", "uw", "gr", "gw", "rw", "bur", "buw", "bug", "brg", "brw", "bgw", "wur", "wug", "wrg", "rgu"); @Test + @Ignore public void playGames() throws GameException, FileNotFoundException { for (int i = 1; i < 100; i++) { logger.info("Playing game: " + i); diff --git a/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java b/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java index 0c0ab908178..d45bf2c6b4e 100644 --- a/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java +++ b/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java @@ -82,6 +82,20 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement } /** + * Removes all cards from player's hand from the game. + * Usually this should be used once before initialization to set the players hand. + * + * @param player {@link Player} to remove all cards from hand. + */ + public void removeAllCardsFromHand(Player player) { + if (player.equals(playerA)) { + commandsA.put(Constants.Zone.HAND, "clear"); + } else if (player.equals(playerB)) { + commandsB.put(Constants.Zone.HAND, "clear"); + } + } + + /** * Add a card to specified zone of specified player. * * @param gameZone {@link Constants.Zone} to add cards to. @@ -361,16 +375,38 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement * @param count Expected count. */ public void assertCounterCount(String cardName, CounterType type, int count) throws AssertionError { - int actualCount = 0; - for (Permanent permanent : currentGame.getBattlefield().getAllPermanents()) { - if (permanent.getName().equals(cardName)) { - actualCount += permanent.getCounters().getCount(type); - } + Permanent found = null; + for (Permanent permanent : currentGame.getBattlefield().getAllActivePermanents()) { + if (permanent.getName().equals(cardName)) { + found = permanent; + } } - Assert.assertEquals("(Battlefield) Counter counts are not equal (" + cardName + ":" + type + ")", count, actualCount); + + Assert.assertNotNull("There is no such permanent on the battlefield, cardName=" + cardName, found); + + Assert.assertEquals("(Battlefield) Counter counts are not equal (" + cardName + ":" + type + ")", count, found.getCounters().getCount(type)); } /** + * Assert whether a permanent is tapped or not + * + * @param cardName Name of the permanent that should be checked. + * @param tapped Whether the permanent is tapped or not + */ + public void assertTapped(String cardName, boolean tapped) throws AssertionError { + Permanent found = null; + for (Permanent permanent : currentGame.getBattlefield().getAllActivePermanents()) { + if (permanent.getName().equals(cardName)) { + found = permanent; + } + } + + Assert.assertNotNull("There is no such permanent on the battlefield, cardName=" + cardName, found); + + Assert.assertEquals("(Battlefield) Tapped state is not equal (" + cardName + ")", tapped, found.isTapped()); + } + + /** * Assert card count in player's hand. * * @param player {@link Player} who's hand should be counted. @@ -442,6 +478,10 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement player.addAction(turnNum, step, "activate:Cast " + cardName + ";target=" + targetName); } + public void activateAbility(int turnNum, PhaseStep step, TestPlayer player, String ability) { + player.addAction(turnNum, step, "activate:" + ability); + } + public void activateAbility(int turnNum, PhaseStep step, TestPlayer player, String ability, Player target) { player.addAction(turnNum, step, "activate:" + ability + ";target=" + target.getName()); } diff --git a/Mage/src/mage/abilities/ActivatedAbilityImpl.java b/Mage/src/mage/abilities/ActivatedAbilityImpl.java index e10e2497863..3d32511fa3f 100644 --- a/Mage/src/mage/abilities/ActivatedAbilityImpl.java +++ b/Mage/src/mage/abilities/ActivatedAbilityImpl.java @@ -32,9 +32,9 @@ import java.util.UUID; import mage.Constants.AbilityType; import mage.Constants.TimingRule; import mage.Constants.Zone; +import mage.MageObject; import mage.abilities.costs.Cost; import mage.abilities.costs.Costs; -import mage.abilities.costs.mana.ManaCost; import mage.abilities.costs.mana.ManaCosts; import mage.abilities.costs.mana.PhyrexianManaCost; import mage.abilities.effects.Effect; @@ -176,7 +176,11 @@ public abstract class ActivatedAbilityImpl> ex protected String getMessageText(Game game) { StringBuilder sb = new StringBuilder(); - sb.append(game.getObject(this.sourceId).getName()); + MageObject object = game.getObject(this.sourceId); + if (object != null) + sb.append(object.getName()); + else + sb.append("unknown"); if (getTargets().size() > 0) { sb.append(" targeting "); for (Target target: getTargets()) { diff --git a/Mage/src/mage/abilities/TriggeredAbilities.java b/Mage/src/mage/abilities/TriggeredAbilities.java index f51634e0735..f26b0148396 100644 --- a/Mage/src/mage/abilities/TriggeredAbilities.java +++ b/Mage/src/mage/abilities/TriggeredAbilities.java @@ -28,9 +28,9 @@ package mage.abilities; +import java.util.HashMap; +import java.util.Map; import java.util.UUID; -import mage.Constants; -import mage.Constants.Zone; import mage.MageObject; import mage.game.Game; import mage.game.events.GameEvent; @@ -39,18 +39,22 @@ import mage.game.events.GameEvent; * * @author BetaSteward_at_googlemail.com */ -public class TriggeredAbilities extends AbilitiesImpl { +public class TriggeredAbilities extends HashMap { public TriggeredAbilities() {} public TriggeredAbilities(final TriggeredAbilities abilities) { - super(abilities); + for (Map.Entry entry: abilities.entrySet()) { + this.put(entry.getKey(), entry.getValue().copy()); + } } public void checkTriggers(GameEvent event, Game game) { - for (TriggeredAbility ability: this) { + for (TriggeredAbility ability: this.values()) { if (ability.isInUseableZone(game)) { - MageObject object = game.getObject(ability.getSourceId()); + MageObject object = game.getLastKnownInformation(ability.getSourceId(), event.getZone()); + if (object == null) + object = game.getObject(ability.getSourceId()); if (object != null && object.getAbilities().contains(ability)) { if (ability.checkTrigger(event, game)) { ability.trigger(game, ability.getControllerId()); @@ -59,8 +63,11 @@ public class TriggeredAbilities extends AbilitiesImpl { } } } + + public void add(TriggeredAbility ability) { + this.put(ability.getId(), ability); + } - @Override public TriggeredAbilities copy() { return new TriggeredAbilities(this); } diff --git a/Mage/src/mage/abilities/costs/common/ExileFromGraveCost.java b/Mage/src/mage/abilities/costs/common/ExileFromGraveCost.java index a1be6a7b785..0709332da55 100644 --- a/Mage/src/mage/abilities/costs/common/ExileFromGraveCost.java +++ b/Mage/src/mage/abilities/costs/common/ExileFromGraveCost.java @@ -79,7 +79,7 @@ public class ExileFromGraveCost extends CostImpl { @Override public boolean canPay(UUID sourceId, UUID controllerId, Game game) { - return targets.canChoose(controllerId, controllerId, game); + return targets.canChoose(controllerId, game); } @Override diff --git a/Mage/src/mage/abilities/costs/common/ReturnToHandTargetCost.java b/Mage/src/mage/abilities/costs/common/ReturnToHandTargetCost.java index 5d62c9176cf..7a6d2508d1c 100644 --- a/Mage/src/mage/abilities/costs/common/ReturnToHandTargetCost.java +++ b/Mage/src/mage/abilities/costs/common/ReturnToHandTargetCost.java @@ -71,7 +71,7 @@ public class ReturnToHandTargetCost extends CostImpl { @Override public boolean canPay(UUID sourceId, UUID controllerId, Game game) { - return targets.canChoose(controllerId, controllerId, game); + return targets.canChoose(controllerId, game); } @Override diff --git a/Mage/src/mage/abilities/costs/common/SacrificeTargetCost.java b/Mage/src/mage/abilities/costs/common/SacrificeTargetCost.java index 7d95a81591b..eef4de0b656 100644 --- a/Mage/src/mage/abilities/costs/common/SacrificeTargetCost.java +++ b/Mage/src/mage/abilities/costs/common/SacrificeTargetCost.java @@ -74,7 +74,7 @@ public class SacrificeTargetCost extends CostImpl { @Override public boolean canPay(UUID sourceId, UUID controllerId, Game game) { - return targets.canChoose(sourceId, controllerId, game); + return targets.canChoose(controllerId, game); } @Override diff --git a/Mage/src/mage/game/permanent/PermanentCard.java b/Mage/src/mage/game/permanent/PermanentCard.java index 4555adc99b7..dd3f8dc0a31 100644 --- a/Mage/src/mage/game/permanent/PermanentCard.java +++ b/Mage/src/mage/game/permanent/PermanentCard.java @@ -96,6 +96,7 @@ public class PermanentCard extends PermanentImpl { this.abilities.clear(); this.abilities.addAll(card.getAbilities()); this.abilities.setControllerId(this.controllerId); + this.watchers.addAll(card.getWatchers()); this.cardType.clear(); this.cardType.addAll(card.getCardType()); this.color = card.getColor().copy();