From 080a1b883ca712fb833d8ab899ca4f5b8e3d050d Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Fri, 4 Mar 2016 12:21:47 +0100 Subject: [PATCH] Wild Pair - fixed condition handling. --- .../MyojinOfCleansingFire.java | 4 +- .../MyojinOfInfiniteRage.java | 4 +- .../championsofkamigawa/MyojinOfLifesWeb.java | 4 +- .../MyojinOfNightsReach.java | 4 +- .../MyojinOfSeeingWinds.java | 4 +- .../mage/sets/commander/DreadCacodemon.java | 4 +- .../commander2014/AngelOfTheDireHour.java | 4 +- .../commander2014/BreachingLeviathan.java | 4 +- .../mage/sets/darksteel/FurnaceDragon.java | 4 +- .../sets/divinevsdemonic/ReiverDemon.java | 4 +- .../sets/dragonsmaze/ScionOfVituGhazi.java | 4 +- .../dragonsoftarkir/DeathbringerRegent.java | 4 +- .../mage/sets/modernmasters/Epochrasite.java | 4 +- .../src/mage/sets/planarchaos/WildPair.java | 50 +++++++++++++-- .../sets/saviorsofkamigawa/InameAsOne.java | 4 +- .../mage/sets/sorinvstibalt/CoalStoker.java | 4 +- .../tenthedition/PhageTheUntouchable.java | 4 +- .../EntersTheBattlefieldTriggerTest.java | 64 +++++++++++++------ ....java => CastFromHandSourceCondition.java} | 2 +- 19 files changed, 120 insertions(+), 60 deletions(-) rename Mage/src/main/java/mage/abilities/condition/common/{CastFromHandCondition.java => CastFromHandSourceCondition.java} (93%) diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/MyojinOfCleansingFire.java b/Mage.Sets/src/mage/sets/championsofkamigawa/MyojinOfCleansingFire.java index 17859d23648..4835f20c8bd 100644 --- a/Mage.Sets/src/mage/sets/championsofkamigawa/MyojinOfCleansingFire.java +++ b/Mage.Sets/src/mage/sets/championsofkamigawa/MyojinOfCleansingFire.java @@ -35,7 +35,7 @@ import mage.MageInt; import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.condition.common.CastFromHandCondition; +import mage.abilities.condition.common.CastFromHandSourceCondition; import mage.abilities.condition.common.SourceHasCounterCondition; import mage.abilities.costs.common.RemoveCountersSourceCost; import mage.abilities.decorator.ConditionalContinuousEffect; @@ -74,7 +74,7 @@ public class MyojinOfCleansingFire extends CardImpl { this.getSpellAbility().addWatcher(new CastFromHandWatcher()); // Myojin of Cleansing Fire enters the battlefield with a divinity counter on it if you cast it from your hand. - this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.DIVINITY.createInstance()), new CastFromHandCondition(), ""), "{this} enters the battlefield with a divinity counter on it if you cast it from your hand")); + this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.DIVINITY.createInstance()), new CastFromHandSourceCondition(), ""), "{this} enters the battlefield with a divinity counter on it if you cast it from your hand")); // Myojin of Cleansing Fire is indestructible as long as it has a divinity counter on it. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(new GainAbilitySourceEffect(IndestructibleAbility.getInstance(), Duration.WhileOnBattlefield), new SourceHasCounterCondition(CounterType.DIVINITY), "{this} is indestructible as long as it has a divinity counter on it"))); diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/MyojinOfInfiniteRage.java b/Mage.Sets/src/mage/sets/championsofkamigawa/MyojinOfInfiniteRage.java index ac250e6c060..7be1669a4b4 100644 --- a/Mage.Sets/src/mage/sets/championsofkamigawa/MyojinOfInfiniteRage.java +++ b/Mage.Sets/src/mage/sets/championsofkamigawa/MyojinOfInfiniteRage.java @@ -35,7 +35,7 @@ import mage.MageInt; import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.condition.common.CastFromHandCondition; +import mage.abilities.condition.common.CastFromHandSourceCondition; import mage.abilities.condition.common.SourceHasCounterCondition; import mage.abilities.costs.common.RemoveCountersSourceCost; import mage.abilities.decorator.ConditionalContinuousEffect; @@ -70,7 +70,7 @@ public class MyojinOfInfiniteRage extends CardImpl { this.getSpellAbility().addWatcher(new CastFromHandWatcher()); // Myojin of Infinite Rage enters the battlefield with a divinity counter on it if you cast it from your hand. - this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.DIVINITY.createInstance()), new CastFromHandCondition(), ""), "{this} enters the battlefield with a divinity counter on it if you cast it from your hand")); + this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.DIVINITY.createInstance()), new CastFromHandSourceCondition(), ""), "{this} enters the battlefield with a divinity counter on it if you cast it from your hand")); // Myojin of Infinite Rage is indestructible as long as it has a divinity counter on it. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(new GainAbilitySourceEffect(IndestructibleAbility.getInstance(), Duration.WhileOnBattlefield), new SourceHasCounterCondition(CounterType.DIVINITY), "{this} is indestructible as long as it has a divinity counter on it"))); diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/MyojinOfLifesWeb.java b/Mage.Sets/src/mage/sets/championsofkamigawa/MyojinOfLifesWeb.java index c4dac7d5dac..00c411cb2bf 100644 --- a/Mage.Sets/src/mage/sets/championsofkamigawa/MyojinOfLifesWeb.java +++ b/Mage.Sets/src/mage/sets/championsofkamigawa/MyojinOfLifesWeb.java @@ -35,7 +35,7 @@ import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.condition.common.CastFromHandCondition; +import mage.abilities.condition.common.CastFromHandSourceCondition; import mage.abilities.condition.common.SourceHasCounterCondition; import mage.abilities.costs.common.RemoveCountersSourceCost; import mage.abilities.decorator.ConditionalContinuousEffect; @@ -75,7 +75,7 @@ public class MyojinOfLifesWeb extends CardImpl { this.getSpellAbility().addWatcher(new CastFromHandWatcher()); // Myojin of Life's Web enters the battlefield with a divinity counter on it if you cast it from your hand. - this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.DIVINITY.createInstance()), new CastFromHandCondition(), ""), "{this} enters the battlefield with a divinity counter on it if you cast it from your hand")); + this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.DIVINITY.createInstance()), new CastFromHandSourceCondition(), ""), "{this} enters the battlefield with a divinity counter on it if you cast it from your hand")); // Myojin of Life's Web is indestructible as long as it has a divinity counter on it. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(new GainAbilitySourceEffect(IndestructibleAbility.getInstance(), Duration.WhileOnBattlefield), diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/MyojinOfNightsReach.java b/Mage.Sets/src/mage/sets/championsofkamigawa/MyojinOfNightsReach.java index ac83c62d9e5..9e2cdb46aad 100644 --- a/Mage.Sets/src/mage/sets/championsofkamigawa/MyojinOfNightsReach.java +++ b/Mage.Sets/src/mage/sets/championsofkamigawa/MyojinOfNightsReach.java @@ -35,7 +35,7 @@ import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.condition.common.CastFromHandCondition; +import mage.abilities.condition.common.CastFromHandSourceCondition; import mage.abilities.condition.common.SourceHasCounterCondition; import mage.abilities.costs.common.RemoveCountersSourceCost; import mage.abilities.decorator.ConditionalContinuousEffect; @@ -68,7 +68,7 @@ public class MyojinOfNightsReach extends CardImpl { this.getSpellAbility().addWatcher(new CastFromHandWatcher()); // Myojin of Night's Reach enters the battlefield with a divinity counter on it if you cast it from your hand. - this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.DIVINITY.createInstance()), new CastFromHandCondition(), ""), "{this} enters the battlefield with a divinity counter on it if you cast it from your hand")); + this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.DIVINITY.createInstance()), new CastFromHandSourceCondition(), ""), "{this} enters the battlefield with a divinity counter on it if you cast it from your hand")); // Myojin of Night's Reach is indestructible as long as it has a divinity counter on it. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(new GainAbilitySourceEffect(IndestructibleAbility.getInstance(), Duration.WhileOnBattlefield), new SourceHasCounterCondition(CounterType.DIVINITY), "{this} is indestructible as long as it has a divinity counter on it"))); diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/MyojinOfSeeingWinds.java b/Mage.Sets/src/mage/sets/championsofkamigawa/MyojinOfSeeingWinds.java index c33b5db0d68..609bf3e2b4a 100644 --- a/Mage.Sets/src/mage/sets/championsofkamigawa/MyojinOfSeeingWinds.java +++ b/Mage.Sets/src/mage/sets/championsofkamigawa/MyojinOfSeeingWinds.java @@ -35,7 +35,7 @@ import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.condition.common.CastFromHandCondition; +import mage.abilities.condition.common.CastFromHandSourceCondition; import mage.abilities.condition.common.SourceHasCounterCondition; import mage.abilities.costs.common.RemoveCountersSourceCost; import mage.abilities.decorator.ConditionalContinuousEffect; @@ -73,7 +73,7 @@ public class MyojinOfSeeingWinds extends CardImpl { this.getSpellAbility().addWatcher(new CastFromHandWatcher()); // Myojin of Seeing Winds enters the battlefield with a divinity counter on it if you cast it from your hand. - this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.DIVINITY.createInstance()), new CastFromHandCondition(), ""), "{this} enters the battlefield with a divinity counter on it if you cast it from your hand")); + this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.DIVINITY.createInstance()), new CastFromHandSourceCondition(), ""), "{this} enters the battlefield with a divinity counter on it if you cast it from your hand")); // Myojin of Seeing Winds is indestructible as long as it has a divinity counter on it. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(new GainAbilitySourceEffect(IndestructibleAbility.getInstance(), Duration.WhileOnBattlefield), new SourceHasCounterCondition(CounterType.DIVINITY), "{this} is indestructible as long as it has a divinity counter on it"))); diff --git a/Mage.Sets/src/mage/sets/commander/DreadCacodemon.java b/Mage.Sets/src/mage/sets/commander/DreadCacodemon.java index 0af6bfc333b..265e5ce1bab 100644 --- a/Mage.Sets/src/mage/sets/commander/DreadCacodemon.java +++ b/Mage.Sets/src/mage/sets/commander/DreadCacodemon.java @@ -31,7 +31,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.condition.common.CastFromHandCondition; +import mage.abilities.condition.common.CastFromHandSourceCondition; import mage.abilities.decorator.ConditionalTriggeredAbility; import mage.abilities.effects.common.DestroyAllEffect; import mage.abilities.effects.common.TapAllEffect; @@ -71,7 +71,7 @@ public class DreadCacodemon extends CardImpl { // if you cast it from your hand, destroy all creatures your opponents control, then tap all other creatures you control. TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new DestroyAllEffect(opponentsCreatures, false)); ability.addEffect(new TapAllEffect(otherCreaturesYouControl)); - this.addAbility(new ConditionalTriggeredAbility(ability, new CastFromHandCondition(), + this.addAbility(new ConditionalTriggeredAbility(ability, new CastFromHandSourceCondition(), "When {this} enters the battlefield, if you cast it from your hand, destroy all creatures your opponents control, then tap all other creatures you control."), new CastFromHandWatcher()); } diff --git a/Mage.Sets/src/mage/sets/commander2014/AngelOfTheDireHour.java b/Mage.Sets/src/mage/sets/commander2014/AngelOfTheDireHour.java index 04336e553d5..49a589e5b5a 100644 --- a/Mage.Sets/src/mage/sets/commander2014/AngelOfTheDireHour.java +++ b/Mage.Sets/src/mage/sets/commander2014/AngelOfTheDireHour.java @@ -30,7 +30,7 @@ package mage.sets.commander2014; import java.util.UUID; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.condition.common.CastFromHandCondition; +import mage.abilities.condition.common.CastFromHandSourceCondition; import mage.abilities.decorator.ConditionalTriggeredAbility; import mage.abilities.effects.common.ExileAllEffect; import mage.abilities.keyword.FlashAbility; @@ -62,7 +62,7 @@ public class AngelOfTheDireHour extends CardImpl { // When Angel of the Dire Hour enters the battlefield, if you cast it from your hand, exile all attacking creatures. this.addAbility(new ConditionalTriggeredAbility( new EntersBattlefieldTriggeredAbility(new ExileAllEffect(new FilterAttackingCreature("attacking creatures")), false), - new CastFromHandCondition(), + new CastFromHandSourceCondition(), "When {this} enters the battlefield, if you cast it from your hand, exile all attacking creatures."), new CastFromHandWatcher()); } diff --git a/Mage.Sets/src/mage/sets/commander2014/BreachingLeviathan.java b/Mage.Sets/src/mage/sets/commander2014/BreachingLeviathan.java index e8e24c4d57c..4bc14d7bfca 100644 --- a/Mage.Sets/src/mage/sets/commander2014/BreachingLeviathan.java +++ b/Mage.Sets/src/mage/sets/commander2014/BreachingLeviathan.java @@ -32,7 +32,7 @@ import mage.MageInt; import mage.ObjectColor; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.condition.common.CastFromHandCondition; +import mage.abilities.condition.common.CastFromHandSourceCondition; import mage.abilities.decorator.ConditionalTriggeredAbility; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.OneShotEffect; @@ -66,7 +66,7 @@ public class BreachingLeviathan extends CardImpl { // When Breaching Leviathan enters the battlefield, if you cast it from your hand, tap all nonblue creatures. Those creatures don't untap during their controllers' next untap steps. this.addAbility(new ConditionalTriggeredAbility( new EntersBattlefieldTriggeredAbility(new BreachingLeviathanEffect(), false), - new CastFromHandCondition(), + new CastFromHandSourceCondition(), "When {this} enters the battlefield, if you cast it from your hand, tap all nonblue creatures. Those creatures don't untap during their controllers' next untap steps."), new CastFromHandWatcher()); } diff --git a/Mage.Sets/src/mage/sets/darksteel/FurnaceDragon.java b/Mage.Sets/src/mage/sets/darksteel/FurnaceDragon.java index 0e9d02637b8..77638cd428f 100644 --- a/Mage.Sets/src/mage/sets/darksteel/FurnaceDragon.java +++ b/Mage.Sets/src/mage/sets/darksteel/FurnaceDragon.java @@ -30,7 +30,7 @@ package mage.sets.darksteel; import java.util.UUID; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.condition.common.CastFromHandCondition; +import mage.abilities.condition.common.CastFromHandSourceCondition; import mage.abilities.decorator.ConditionalTriggeredAbility; import mage.abilities.effects.common.ExileAllEffect; import mage.abilities.keyword.AffinityForArtifactsAbility; @@ -70,7 +70,7 @@ public class FurnaceDragon extends CardImpl { // When Furnace Dragon enters the battlefield, if you cast it from your hand, exile all artifacts. this.addAbility(new ConditionalTriggeredAbility( new EntersBattlefieldTriggeredAbility(new ExileAllEffect(filter), false), - new CastFromHandCondition(), + new CastFromHandSourceCondition(), "When {this} enters the battlefield, if you cast it from your hand, exile all artifacts."), new CastFromHandWatcher()); } diff --git a/Mage.Sets/src/mage/sets/divinevsdemonic/ReiverDemon.java b/Mage.Sets/src/mage/sets/divinevsdemonic/ReiverDemon.java index 1278473e692..f3eb54962bd 100644 --- a/Mage.Sets/src/mage/sets/divinevsdemonic/ReiverDemon.java +++ b/Mage.Sets/src/mage/sets/divinevsdemonic/ReiverDemon.java @@ -31,7 +31,7 @@ import java.util.UUID; import mage.MageInt; import mage.ObjectColor; import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.condition.common.CastFromHandCondition; +import mage.abilities.condition.common.CastFromHandSourceCondition; import mage.abilities.decorator.ConditionalTriggeredAbility; import mage.abilities.effects.common.DestroyAllEffect; import mage.abilities.keyword.FlyingAbility; @@ -70,7 +70,7 @@ public class ReiverDemon extends CardImpl { // When Reiver Demon enters the battlefield, if you cast it from your hand, destroy all nonartifact, nonblack creatures. They can't be regenerated. this.addAbility(new ConditionalTriggeredAbility( new EntersBattlefieldTriggeredAbility(new DestroyAllEffect(filter, true), false), - new CastFromHandCondition(), + new CastFromHandSourceCondition(), "When {this} enters the battlefield, if you cast it from your hand, destroy all nonartifact, nonblack creatures. They can't be regenerated."), new CastFromHandWatcher()); } diff --git a/Mage.Sets/src/mage/sets/dragonsmaze/ScionOfVituGhazi.java b/Mage.Sets/src/mage/sets/dragonsmaze/ScionOfVituGhazi.java index 4c5ea06c015..feb3b83919e 100644 --- a/Mage.Sets/src/mage/sets/dragonsmaze/ScionOfVituGhazi.java +++ b/Mage.Sets/src/mage/sets/dragonsmaze/ScionOfVituGhazi.java @@ -31,7 +31,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.condition.common.CastFromHandCondition; +import mage.abilities.condition.common.CastFromHandSourceCondition; import mage.abilities.decorator.ConditionalTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.PopulateEffect; @@ -57,7 +57,7 @@ public class ScionOfVituGhazi extends CardImpl { TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new BirdToken()), false); ability.addEffect(new PopulateEffect("then")); - this.addAbility(new ConditionalTriggeredAbility(ability, new CastFromHandCondition(), + this.addAbility(new ConditionalTriggeredAbility(ability, new CastFromHandSourceCondition(), "When {this} enters the battlefield, if you cast it from your hand, put a 1/1 white Bird creature token with flying onto the battlefield, then populate."), new CastFromHandWatcher()); } diff --git a/Mage.Sets/src/mage/sets/dragonsoftarkir/DeathbringerRegent.java b/Mage.Sets/src/mage/sets/dragonsoftarkir/DeathbringerRegent.java index b4b5e194f9c..acae240ee7f 100644 --- a/Mage.Sets/src/mage/sets/dragonsoftarkir/DeathbringerRegent.java +++ b/Mage.Sets/src/mage/sets/dragonsoftarkir/DeathbringerRegent.java @@ -32,7 +32,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.condition.common.CastFromHandCondition; +import mage.abilities.condition.common.CastFromHandSourceCondition; import mage.abilities.decorator.ConditionalTriggeredAbility; import mage.abilities.effects.common.DestroyAllEffect; import mage.abilities.keyword.FlyingAbility; @@ -88,7 +88,7 @@ class DeathbringerRegentCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - return new CastFromHandCondition().apply(game, source) + return new CastFromHandSourceCondition().apply(game, source) && game.getBattlefield().getAllActivePermanents(new FilterCreaturePermanent(), game).size() >= 6; } } diff --git a/Mage.Sets/src/mage/sets/modernmasters/Epochrasite.java b/Mage.Sets/src/mage/sets/modernmasters/Epochrasite.java index 6f652e82b4e..42ca701acdd 100644 --- a/Mage.Sets/src/mage/sets/modernmasters/Epochrasite.java +++ b/Mage.Sets/src/mage/sets/modernmasters/Epochrasite.java @@ -34,7 +34,7 @@ import mage.abilities.Ability; import mage.abilities.common.DiesTriggeredAbility; import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.condition.InvertCondition; -import mage.abilities.condition.common.CastFromHandCondition; +import mage.abilities.condition.common.CastFromHandSourceCondition; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.continuous.GainSuspendEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; @@ -67,7 +67,7 @@ public class Epochrasite extends CardImpl { // Epochrasite enters the battlefield with three +1/+1 counters on it if you didn't cast it from your hand. this.addAbility(new EntersBattlefieldAbility( new AddCountersSourceEffect(CounterType.P1P1.createInstance(3)), - new InvertCondition(new CastFromHandCondition()), + new InvertCondition(new CastFromHandSourceCondition()), "{this} enters the battlefield with three +1/+1 counters on it if you didn't cast it from your hand",""), new CastFromHandWatcher()); diff --git a/Mage.Sets/src/mage/sets/planarchaos/WildPair.java b/Mage.Sets/src/mage/sets/planarchaos/WildPair.java index 9f47914f805..0f917e69404 100644 --- a/Mage.Sets/src/mage/sets/planarchaos/WildPair.java +++ b/Mage.Sets/src/mage/sets/planarchaos/WildPair.java @@ -31,15 +31,15 @@ import java.util.UUID; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; -import mage.abilities.condition.common.CastFromHandCondition; +import mage.abilities.condition.Condition; import mage.abilities.decorator.ConditionalTriggeredAbility; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect; import mage.cards.CardImpl; import mage.cards.CardsImpl; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.Rarity; +import mage.constants.SetTargetPointer; import mage.constants.Zone; import mage.filter.Filter; import mage.filter.common.FilterCreatureCard; @@ -47,25 +47,27 @@ import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.IntComparePredicate; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.game.stack.Spell; import mage.players.Player; import mage.target.common.TargetCardInLibrary; +import mage.watchers.common.CastFromHandWatcher; /** * * @author fenhl */ public class WildPair extends CardImpl { - + public WildPair(UUID ownerID) { super(ownerID, 30, "Wild Pair", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{4}{G}{G}"); this.expansionSetCode = "PLC"; // Whenever a creature enters the battlefield, if you cast it from your hand, you may search your library for a creature card with the same total power and toughness and put it onto the battlefield. If you do, shuffle your library. this.addAbility(new ConditionalTriggeredAbility( - new EntersBattlefieldAllTriggeredAbility(Zone.BATTLEFIELD, new WildPairEffect(), new FilterCreaturePermanent("a creature"), true), - new CastFromHandCondition(), + new EntersBattlefieldAllTriggeredAbility(Zone.BATTLEFIELD, new WildPairEffect(), new FilterCreaturePermanent("a creature"), true, SetTargetPointer.PERMANENT, ""), + new CastFromHandTargetCondition(), "Whenever a creature enters the battlefield, if you cast it from your hand, you may search your library for a creature card with the same total power and toughness and put it onto the battlefield. If you do, shuffle your library." - )); + ), new CastFromHandWatcher()); } public WildPair(final WildPair card) { @@ -110,7 +112,7 @@ class WildPairEffect extends OneShotEffect { } } controller.shuffleLibrary(game); - return true; + return true; } } return false; @@ -137,3 +139,37 @@ class TotalPowerAndToughnessPredicate extends IntComparePredicate { return "TotalPowerAndToughness" + super.toString(); } } + +class CastFromHandTargetCondition implements Condition { + + @Override + public boolean apply(Game game, Ability source) { + UUID targetId = source.getEffects().get(0).getTargetPointer().getFirst(game, source); + Permanent permanent = game.getPermanentEntering(targetId); + int zccDiff = 0; + if (permanent == null) { + permanent = game.getPermanentOrLKIBattlefield(targetId); // can be alredy again removed from battlefield so also check LKI + zccDiff = -1; + } + if (permanent != null) { + // check that the spell is still in the LKI + Spell spell = game.getStack().getSpell(targetId); + if (spell == null || spell.getZoneChangeCounter(game) != permanent.getZoneChangeCounter(game) + zccDiff) { + if (game.getLastKnownInformation(targetId, Zone.STACK, permanent.getZoneChangeCounter(game) + zccDiff) == null) { + return false; + } + } + CastFromHandWatcher watcher = (CastFromHandWatcher) game.getState().getWatchers().get(CastFromHandWatcher.class.getName()); + if (watcher != null && watcher.spellWasCastFromHand(targetId)) { + return true; + } + } + return false; + } + + @Override + public String toString() { + return "you cast it from your hand"; + } + +} diff --git a/Mage.Sets/src/mage/sets/saviorsofkamigawa/InameAsOne.java b/Mage.Sets/src/mage/sets/saviorsofkamigawa/InameAsOne.java index 769130d982f..e8ac8053b99 100644 --- a/Mage.Sets/src/mage/sets/saviorsofkamigawa/InameAsOne.java +++ b/Mage.Sets/src/mage/sets/saviorsofkamigawa/InameAsOne.java @@ -33,7 +33,7 @@ import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.DiesTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.condition.common.CastFromHandCondition; +import mage.abilities.condition.common.CastFromHandSourceCondition; import mage.abilities.decorator.ConditionalTriggeredAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; @@ -77,7 +77,7 @@ public class InameAsOne extends CardImpl { // When Iname as One enters the battlefield, if you cast it from your hand, you may search your library for a Spirit permanent card, put it onto the battlefield, then shuffle your library. this.addAbility(new ConditionalTriggeredAbility( new EntersBattlefieldTriggeredAbility(new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(0, 1, filter)), true), - new CastFromHandCondition(), + new CastFromHandSourceCondition(), "When {this} enters the battlefield, if you cast it from your hand, you may search your library for a Spirit permanent card, put it onto the battlefield, then shuffle your library."), new CastFromHandWatcher()); diff --git a/Mage.Sets/src/mage/sets/sorinvstibalt/CoalStoker.java b/Mage.Sets/src/mage/sets/sorinvstibalt/CoalStoker.java index 403d9c7a95c..a8bae0da416 100644 --- a/Mage.Sets/src/mage/sets/sorinvstibalt/CoalStoker.java +++ b/Mage.Sets/src/mage/sets/sorinvstibalt/CoalStoker.java @@ -31,7 +31,7 @@ import java.util.UUID; import mage.MageInt; import mage.Mana; import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.condition.common.CastFromHandCondition; +import mage.abilities.condition.common.CastFromHandSourceCondition; import mage.abilities.decorator.ConditionalTriggeredAbility; import mage.abilities.effects.common.BasicManaEffect; import mage.cards.CardImpl; @@ -55,7 +55,7 @@ public class CoalStoker extends CardImpl { // When Coal Stoker enters the battlefield, if you cast it from your hand, add {R}{R}{R} to your mana pool. this.addAbility(new ConditionalTriggeredAbility( new EntersBattlefieldTriggeredAbility(new BasicManaEffect(new Mana(3, 0, 0, 0, 0, 0, 0, 0)), false), - new CastFromHandCondition(), + new CastFromHandSourceCondition(), "When {this} enters the battlefield, if you cast it from your hand, add {R}{R}{R} to your mana pool."), new CastFromHandWatcher()); } diff --git a/Mage.Sets/src/mage/sets/tenthedition/PhageTheUntouchable.java b/Mage.Sets/src/mage/sets/tenthedition/PhageTheUntouchable.java index 61e5130d2e8..ce4651de8fa 100644 --- a/Mage.Sets/src/mage/sets/tenthedition/PhageTheUntouchable.java +++ b/Mage.Sets/src/mage/sets/tenthedition/PhageTheUntouchable.java @@ -33,7 +33,7 @@ import mage.abilities.common.DealsCombatDamageToACreatureTriggeredAbility; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.InvertCondition; -import mage.abilities.condition.common.CastFromHandCondition; +import mage.abilities.condition.common.CastFromHandSourceCondition; import mage.abilities.decorator.ConditionalTriggeredAbility; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.effects.common.LoseGameSourceControllerEffect; @@ -62,7 +62,7 @@ public class PhageTheUntouchable extends CardImpl { // When Phage the Untouchable enters the battlefield, if you didn't cast it from your hand, you lose the game. this.addAbility(new ConditionalTriggeredAbility( new EntersBattlefieldTriggeredAbility(new LoseGameSourceControllerEffect(), false), - new InvertCondition(new CastFromHandCondition()), + new InvertCondition(new CastFromHandSourceCondition()), "When {this} enters the battlefield, if you didn't cast it from your hand, you lose the game" ), new CastFromHandWatcher()); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/EntersTheBattlefieldTriggerTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/EntersTheBattlefieldTriggerTest.java index 1fe8be8bb1a..123ce672da4 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/EntersTheBattlefieldTriggerTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/EntersTheBattlefieldTriggerTest.java @@ -130,72 +130,73 @@ public class EntersTheBattlefieldTriggerTest extends CardTestPlayerBase { assertLife(playerA, 15); assertLife(playerB, 20); } - + /** * Dread Cacodemon's abilities should only trigger when cast from hand. - * - * Testing when cast from hand abilities take effect. - * Cast from hand destroys opponents creatures and taps all other creatures owner controls. + * + * Testing when cast from hand abilities take effect. Cast from hand + * destroys opponents creatures and taps all other creatures owner controls. */ @Test public void testDreadCacodemonConditionTrue() { addCard(Zone.BATTLEFIELD, playerA, "Swamp", 10); - + // When Dread Cacodemon enters the battlefield, if you cast it from your hand, destroy all creatures your opponents control, then tap all other creatures you control. addCard(Zone.HAND, playerA, "Dread Cacodemon", 1); // 8/8 - {7}{B}{B}{B} - + addCard(Zone.BATTLEFIELD, playerB, "Swamp", 2); - + // Protection from white, first strike addCard(Zone.BATTLEFIELD, playerA, "Black Knight", 2); // {B}{B} // Deathtouch addCard(Zone.BATTLEFIELD, playerB, "Typhoid Rats", 2); // {B} - + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Dread Cacodemon"); setStopAt(1, PhaseStep.END_TURN); - + execute(); assertPermanentCount(playerB, "Typhoid Rats", 0); assertPermanentCount(playerA, "Dread Cacodemon", 1); - assertPermanentCount(playerA, "Black Knight", 2); + assertPermanentCount(playerA, "Black Knight", 2); assertTappedCount("Black Knight", true, 2); assertTapped("Dread Cacodemon", false); } - - /** + + /** * Dread Cacodemon's abilities should only trigger when cast from hand. - * + * * Testing when card is not cast from hand, abilities do not take effect. - * All opponents creatures remain alive and owner's creatures are not tapped. + * All opponents creatures remain alive and owner's creatures are not + * tapped. */ @Test public void testDreadCacodemonConditionFalse() { addCard(Zone.BATTLEFIELD, playerA, "Swamp", 10); - + // When Dread Cacodemon enters the battlefield, if you cast it from your hand, destroy all creatures your opponents control, then tap all other creatures you control. addCard(Zone.GRAVEYARD, playerA, "Dread Cacodemon", 1); // 8/8 - {7}{B}{B}{B} // Put target creature card from a graveyard onto the battlefield under your control. You lose life equal to its converted mana cost. addCard(Zone.HAND, playerA, "Reanimate", 1); // {B} - + addCard(Zone.BATTLEFIELD, playerB, "Swamp", 2); - + // Protection from white, first strike addCard(Zone.BATTLEFIELD, playerA, "Black Knight", 2); // {B}{B} // Deathtouch addCard(Zone.BATTLEFIELD, playerB, "Typhoid Rats", 2); // {B} - + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Reanimate", "Dread Cacodemon"); setStopAt(1, PhaseStep.END_TURN); - + execute(); assertPermanentCount(playerB, "Typhoid Rats", 2); assertGraveyardCount(playerA, "Reanimate", 1); assertPermanentCount(playerA, "Dread Cacodemon", 1); - assertPermanentCount(playerA, "Black Knight", 2); + assertPermanentCount(playerA, "Black Knight", 2); assertTappedCount("Black Knight", false, 2); assertTapped("Dread Cacodemon", false); @@ -203,4 +204,27 @@ public class EntersTheBattlefieldTriggerTest extends CardTestPlayerBase { assertLife(playerB, 20); } + /** + * Test that the cast from hand condition works for target permanent + * + */ + @Test + public void testWildPair() { + + // Whenever a creature enters the battlefield, if you cast it from your hand, you may search your library for a creature card with the same total power and toughness and put it onto the battlefield. If you do, shuffle your library. + addCard(Zone.BATTLEFIELD, playerA, "Wild Pair"); + addCard(Zone.HAND, playerA, "Silvercoat Lion", 1); + addCard(Zone.BATTLEFIELD, playerA, "Plains", 2); + setChoice(playerA, "Silvercoat Lion"); + addCard(Zone.LIBRARY, playerA, "Silvercoat Lion"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Silvercoat Lion"); + setStopAt(1, PhaseStep.BEGIN_COMBAT); + + execute(); + + assertPermanentCount(playerA, "Silvercoat Lion", 2); + + } + } diff --git a/Mage/src/main/java/mage/abilities/condition/common/CastFromHandCondition.java b/Mage/src/main/java/mage/abilities/condition/common/CastFromHandSourceCondition.java similarity index 93% rename from Mage/src/main/java/mage/abilities/condition/common/CastFromHandCondition.java rename to Mage/src/main/java/mage/abilities/condition/common/CastFromHandSourceCondition.java index d14fc200ac8..99fddbba139 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/CastFromHandCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/CastFromHandSourceCondition.java @@ -13,7 +13,7 @@ import mage.watchers.common.CastFromHandWatcher; * * @author Loki */ -public class CastFromHandCondition implements Condition { +public class CastFromHandSourceCondition implements Condition { @Override public boolean apply(Game game, Ability source) {