From 66a341e1a2d89f090fedf0ea33cb88d903a44f04 Mon Sep 17 00:00:00 2001 From: LoneFox Date: Sat, 26 Sep 2015 10:09:34 +0300 Subject: [PATCH 01/16] Add Bird token and use it for existing cards. --- .../mage/sets/bornofthegods/Ornitharch.java | 21 +----- .../src/mage/sets/dragonsmaze/BeckCall.java | 3 +- .../sets/dragonsmaze/ScionOfVituGhazi.java | 21 +----- .../src/mage/sets/judgment/BattleScreech.java | 21 +----- .../sets/returntoravnica/EyesInTheSkies.java | 21 +----- .../returntoravnica/SellerOfSongbirds.java | 19 +---- .../src/mage/sets/zendikar/EmeriaAngel.java | 15 +--- .../mage/game/permanent/token/BirdToken.java | 69 +++++++++++++++++++ 8 files changed, 84 insertions(+), 106 deletions(-) create mode 100644 Mage/src/mage/game/permanent/token/BirdToken.java diff --git a/Mage.Sets/src/mage/sets/bornofthegods/Ornitharch.java b/Mage.Sets/src/mage/sets/bornofthegods/Ornitharch.java index 4095a37719..971027d4b3 100644 --- a/Mage.Sets/src/mage/sets/bornofthegods/Ornitharch.java +++ b/Mage.Sets/src/mage/sets/bornofthegods/Ornitharch.java @@ -40,7 +40,7 @@ import mage.abilities.keyword.TributeAbility; import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Rarity; -import mage.game.permanent.token.Token; +import mage.game.permanent.token.BirdToken; /** * @@ -63,7 +63,7 @@ public class Ornitharch extends CardImpl { // When Ornitharch enters the battlefield, if tribute wasn't paid, put two 1/1 white Bird creature tokens with flying onto the battlefield. TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new BirdToken(), 2), false); this.addAbility(new ConditionalTriggeredAbility(ability, TributeNotPaidCondition.getInstance(), - "When {this} enters the battlefield, if its tribute wasn't paid, put two 1/1 white Bird creature tokens with flying onto the battlefield.")); + "When {this} enters the battlefield, if its tribute wasn't paid, put two 1/1 white Bird creature tokens with flying onto the battlefield.")); } public Ornitharch(final Ornitharch card) { @@ -75,20 +75,3 @@ public class Ornitharch extends CardImpl { return new Ornitharch(this); } } - -class BirdToken extends Token { - - public BirdToken() { - super("Bird", "1/1 white Bird creature tokens with flying"); - this.setOriginalExpansionSetCode("BNG"); - cardType.add(CardType.CREATURE); - color.setWhite(true); - - subtype.add("Bird"); - power = new MageInt(1); - toughness = new MageInt(1); - - this.addAbility(FlyingAbility.getInstance()); - } - -} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/dragonsmaze/BeckCall.java b/Mage.Sets/src/mage/sets/dragonsmaze/BeckCall.java index 8bed02cb90..45ce77a917 100644 --- a/Mage.Sets/src/mage/sets/dragonsmaze/BeckCall.java +++ b/Mage.Sets/src/mage/sets/dragonsmaze/BeckCall.java @@ -39,9 +39,10 @@ import mage.constants.Duration; import mage.constants.Rarity; import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; -import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; +import mage.game.events.GameEvent; import mage.game.permanent.Permanent; +import mage.game.permanent.token.BirdToken; diff --git a/Mage.Sets/src/mage/sets/dragonsmaze/ScionOfVituGhazi.java b/Mage.Sets/src/mage/sets/dragonsmaze/ScionOfVituGhazi.java index 1bc24f70cd..23e1bcc6bd 100644 --- a/Mage.Sets/src/mage/sets/dragonsmaze/ScionOfVituGhazi.java +++ b/Mage.Sets/src/mage/sets/dragonsmaze/ScionOfVituGhazi.java @@ -29,8 +29,6 @@ package mage.sets.dragonsmaze; import java.util.UUID; -import mage.constants.CardType; -import mage.constants.Rarity; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; @@ -38,9 +36,10 @@ import mage.abilities.condition.common.CastFromHandCondition; import mage.abilities.decorator.ConditionalOneShotEffect; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.PopulateEffect; -import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; -import mage.game.permanent.token.Token; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.game.permanent.token.BirdToken; import mage.watchers.common.CastFromHandWatcher; /** @@ -77,17 +76,3 @@ public class ScionOfVituGhazi extends CardImpl { } } - - -class BirdToken extends Token { - public BirdToken() { - super("Bird", "1/1 white Bird creature token with flying"); - cardType.add(CardType.CREATURE); - color.setWhite(true); - subtype.add("Bird"); - power = new MageInt(1); - toughness = new MageInt(1); - addAbility(FlyingAbility.getInstance()); - setOriginalExpansionSetCode("RTR"); - } -} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/judgment/BattleScreech.java b/Mage.Sets/src/mage/sets/judgment/BattleScreech.java index 316c620ae7..f78dc5a738 100644 --- a/Mage.Sets/src/mage/sets/judgment/BattleScreech.java +++ b/Mage.Sets/src/mage/sets/judgment/BattleScreech.java @@ -28,12 +28,10 @@ package mage.sets.judgment; import java.util.UUID; -import mage.MageInt; import mage.ObjectColor; import mage.abilities.costs.common.TapTargetCost; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.keyword.FlashbackAbility; -import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Rarity; @@ -42,7 +40,7 @@ import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.ColorPredicate; import mage.filter.predicate.permanent.TappedPredicate; -import mage.game.permanent.token.Token; +import mage.game.permanent.token.BirdToken; import mage.target.common.TargetControlledCreaturePermanent; /** @@ -79,20 +77,3 @@ public class BattleScreech extends CardImpl { return new BattleScreech(this); } } - -class BirdToken extends Token { - - public BirdToken() { - super("Bird", "1/1 white Bird creature tokens with flying"); - this.setOriginalExpansionSetCode("BNG"); - cardType.add(CardType.CREATURE); - color.setWhite(true); - - subtype.add("Bird"); - power = new MageInt(1); - toughness = new MageInt(1); - - this.addAbility(FlyingAbility.getInstance()); - } - -} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/returntoravnica/EyesInTheSkies.java b/Mage.Sets/src/mage/sets/returntoravnica/EyesInTheSkies.java index 4529c5edf7..d94927b40e 100644 --- a/Mage.Sets/src/mage/sets/returntoravnica/EyesInTheSkies.java +++ b/Mage.Sets/src/mage/sets/returntoravnica/EyesInTheSkies.java @@ -28,14 +28,12 @@ package mage.sets.returntoravnica; import java.util.UUID; -import mage.constants.CardType; -import mage.constants.Rarity; -import mage.MageInt; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.PopulateEffect; -import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; -import mage.game.permanent.token.Token; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.game.permanent.token.BirdToken; /** * @@ -47,7 +45,6 @@ public class EyesInTheSkies extends CardImpl { super(ownerId, 10, "Eyes in the Skies", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{3}{W}"); this.expansionSetCode = "RTR"; - // Put a 1/1 white Bird creature token with flying onto the battlefield, then populate. // (Put a token onto the battlefield that's a copy of a creature token you control.) this.getSpellAbility().addEffect(new CreateTokenEffect(new BirdToken())); @@ -62,17 +59,5 @@ public class EyesInTheSkies extends CardImpl { public EyesInTheSkies copy() { return new EyesInTheSkies(this); } - private class BirdToken extends Token { - - public BirdToken() { - super("Bird", "1/1 white Bird creature token with flying"); - cardType.add(CardType.CREATURE); - color.setWhite(true); - subtype.add("Bird"); - power = new MageInt(1); - toughness = new MageInt(1); - addAbility(FlyingAbility.getInstance()); - } - } } diff --git a/Mage.Sets/src/mage/sets/returntoravnica/SellerOfSongbirds.java b/Mage.Sets/src/mage/sets/returntoravnica/SellerOfSongbirds.java index b4209fc67c..b56d095548 100644 --- a/Mage.Sets/src/mage/sets/returntoravnica/SellerOfSongbirds.java +++ b/Mage.Sets/src/mage/sets/returntoravnica/SellerOfSongbirds.java @@ -28,14 +28,14 @@ package mage.sets.returntoravnica; import java.util.UUID; -import mage.constants.CardType; -import mage.constants.Rarity; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; -import mage.game.permanent.token.Token; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.game.permanent.token.BirdToken; /** * @author LevelX2 @@ -63,17 +63,4 @@ public class SellerOfSongbirds extends CardImpl { public SellerOfSongbirds copy() { return new SellerOfSongbirds(this); } - - private class BirdToken extends Token { - - public BirdToken() { - super("Bird", "1/1 white Bird creature token with flying"); - cardType.add(CardType.CREATURE); - color.setWhite(true); - subtype.add("Bird"); - power = new MageInt(1); - toughness = new MageInt(1); - addAbility(FlyingAbility.getInstance()); - } - } } diff --git a/Mage.Sets/src/mage/sets/zendikar/EmeriaAngel.java b/Mage.Sets/src/mage/sets/zendikar/EmeriaAngel.java index 31e8870245..bd80adab15 100644 --- a/Mage.Sets/src/mage/sets/zendikar/EmeriaAngel.java +++ b/Mage.Sets/src/mage/sets/zendikar/EmeriaAngel.java @@ -36,7 +36,7 @@ import mage.abilities.common.LandfallAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; -import mage.game.permanent.token.Token; +import mage.game.permanent.token.BirdToken; /** * @@ -66,16 +66,3 @@ public class EmeriaAngel extends CardImpl { } } - -class BirdToken extends Token { - - public BirdToken() { - super("Bird", "1/1 white Bird creature token with flying"); - cardType.add(CardType.CREATURE); - color.setWhite(true); - subtype.add("Bird"); - power = new MageInt(1); - toughness = new MageInt(1); - addAbility(FlyingAbility.getInstance()); - } -} \ No newline at end of file diff --git a/Mage/src/mage/game/permanent/token/BirdToken.java b/Mage/src/mage/game/permanent/token/BirdToken.java new file mode 100644 index 0000000000..9100fd4e31 --- /dev/null +++ b/Mage/src/mage/game/permanent/token/BirdToken.java @@ -0,0 +1,69 @@ +/* +* 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.game.permanent.token; + +import java.util.Arrays; +import mage.constants.CardType; +import mage.MageInt; +import mage.abilities.keyword.FlyingAbility; + +/** + * + * @author LoneFox + */ +public class BirdToken extends Token { + + public BirdToken() { + super("Bird", "1/1 white Bird creature token with flying"); + cardType.add(CardType.CREATURE); + color.setWhite(true); + subtype.add("Bird"); + power = new MageInt(1); + toughness = new MageInt(1); + addAbility(FlyingAbility.getInstance()); + availableImageSetCodes.addAll(Arrays.asList("BNG", "RTR", "ZEN")); + } + + public BirdToken(final BirdToken token) { + super(token); + } + + @Override + public BirdToken copy() { + return new BirdToken(this); + } + + @Override + public void setExpansionSetCodeForImage(String code) { + super.setExpansionSetCodeForImage(code); + if (getOriginalExpansionSetCode().equals("BNG")) { + this.setTokenType(1); + } + } +} From 06440fd6060a063e1e12cc48d96e1fa21836e80a Mon Sep 17 00:00:00 2001 From: LoneFox Date: Sat, 26 Sep 2015 10:35:31 +0300 Subject: [PATCH 02/16] Add red and white Soldier token with haste and use it for existing cards. Kill unnecessary custom effect from Assemble the Legion. --- .../mage/sets/dragonsmaze/BlazeCommando.java | 35 +++-------- .../sets/gatecrash/AssembleTheLegion.java | 62 +++---------------- .../mage/sets/gatecrash/SunhomeGuildmage.java | 27 +------- Mage/src/mage/counters/CounterType.java | 1 + .../token/SoldierTokenWithHaste.java | 53 ++++++++++++++++ 5 files changed, 76 insertions(+), 102 deletions(-) create mode 100644 Mage/src/mage/game/permanent/token/SoldierTokenWithHaste.java diff --git a/Mage.Sets/src/mage/sets/dragonsmaze/BlazeCommando.java b/Mage.Sets/src/mage/sets/dragonsmaze/BlazeCommando.java index cc64ee1437..f819fdc768 100644 --- a/Mage.Sets/src/mage/sets/dragonsmaze/BlazeCommando.java +++ b/Mage.Sets/src/mage/sets/dragonsmaze/BlazeCommando.java @@ -31,22 +31,20 @@ package mage.sets.dragonsmaze; import java.util.ArrayList; import java.util.List; 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.TriggeredAbilityImpl; import mage.abilities.effects.common.CreateTokenEffect; -import mage.abilities.keyword.HasteAbility; import mage.cards.Card; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; import mage.game.Game; -import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; +import mage.game.events.GameEvent; import mage.game.permanent.Permanent; -import mage.game.permanent.token.Token; +import mage.game.permanent.token.SoldierTokenWithHaste; import mage.game.stack.StackObject; /** @@ -82,12 +80,13 @@ public class BlazeCommando extends CardImpl { } } + class BlazeCommandoTriggeredAbility extends TriggeredAbilityImpl { private final List handledStackObjects = new ArrayList<>(); public BlazeCommandoTriggeredAbility() { - super(Zone.BATTLEFIELD, new CreateTokenEffect(new BlazeCommandoSoldierToken(), 2), false); + super(Zone.BATTLEFIELD, new CreateTokenEffect(new SoldierTokenWithHaste(), 2), false); } public BlazeCommandoTriggeredAbility(final BlazeCommandoTriggeredAbility ability) { @@ -103,10 +102,10 @@ class BlazeCommandoTriggeredAbility extends TriggeredAbilityImpl { public void reset(Game game) { /** * Blaze Commando's ability triggers each time an instant or sorcery spell you control - * deals damage (or, put another way, the number of times the word “deals” appears in + * deals damage (or, put another way, the number of times the word “deals” appears in * its instructions), no matter how much damage is dealt or how many players or permanents - * are dealt damage. For example, if you cast Punish the Enemy and it “deals 3 damage to - * target player and 3 damage to target creature,” Blaze Commando's ability will trigger + * are dealt damage. For example, if you cast Punish the Enemy and it “deals 3 damage to + * target player and 3 damage to target creature,” Blaze Commando's ability will trigger * once and you'll get two Soldier tokens. */ handledStackObjects.clear(); @@ -138,17 +137,3 @@ class BlazeCommandoTriggeredAbility extends TriggeredAbilityImpl { return new StringBuilder("Whenever an instant or sorcery spell you control deals damage, ").append(super.getRule()).toString(); } } - -class BlazeCommandoSoldierToken extends Token { - - public BlazeCommandoSoldierToken() { - super("Soldier", "1/1 red and white Soldier creature tokens with haste"); - cardType.add(CardType.CREATURE); - color.setRed(true); - color.setWhite(true); - subtype.add("Soldier"); - power = new MageInt(1); - toughness = new MageInt(1); - this.addAbility(HasteAbility.getInstance()); - } -} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/gatecrash/AssembleTheLegion.java b/Mage.Sets/src/mage/sets/gatecrash/AssembleTheLegion.java index faac70e364..7bbe22befb 100644 --- a/Mage.Sets/src/mage/sets/gatecrash/AssembleTheLegion.java +++ b/Mage.Sets/src/mage/sets/gatecrash/AssembleTheLegion.java @@ -28,20 +28,17 @@ package mage.sets.gatecrash; import java.util.UUID; -import mage.constants.CardType; -import mage.constants.Outcome; -import mage.constants.Rarity; -import mage.constants.TargetController; -import mage.constants.Zone; import mage.abilities.Ability; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.dynamicvalue.common.CountersCount; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.cards.CardImpl; -import mage.counters.Counter; -import mage.game.Game; -import mage.game.permanent.Permanent; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.counters.CounterType; +import mage.game.permanent.token.SoldierTokenWithHaste; /** * @@ -55,7 +52,9 @@ public class AssembleTheLegion extends CardImpl { // At the beginning of your upkeep, put a muster counter on Assemble the Legion. Then put a 1/1 red and white Soldier creature token with haste onto the battlefield for each muster counter on Assemble the Legion. - this.addAbility(new BeginningOfUpkeepTriggeredAbility(new AssembleTheLegionEffect(), TargetController.YOU, false)); + Ability ability = new BeginningOfUpkeepTriggeredAbility(new AddCountersSourceEffect(CounterType.MUSTER.createInstance()), TargetController.YOU, false); + ability.addEffect(new CreateTokenEffect(new SoldierTokenWithHaste(), new CountersCount(CounterType.MUSTER))); + this.addAbility(ability); } public AssembleTheLegion(final AssembleTheLegion card) { @@ -67,46 +66,3 @@ public class AssembleTheLegion extends CardImpl { return new AssembleTheLegion(this); } } - -class AssembleTheLegionEffect extends OneShotEffect { - private static final String MUSTER_COUNTER_NAME = "Muster"; - - public AssembleTheLegionEffect() { - super(Outcome.Copy); - this.staticText = "put a muster counter on {this}. Then put a 1/1 red and white Soldier creature token with haste onto the battlefield for each muster counter on {this}"; - } - - public AssembleTheLegionEffect(final AssembleTheLegionEffect effect) { - super(effect); - } - - @Override - public AssembleTheLegionEffect copy() { - return new AssembleTheLegionEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - /* 1/24/2013: If Assemble the Legion isn’t on the battlefield when its ability resolves, - * use the number of muster counters it had when it was last on the battlefield to - * determine how many Soldier tokens to put onto the battlefield. - */ - - Permanent sourcePermanent = game.getPermanent(source.getSourceId()); - int amountCounters = 0; - if (sourcePermanent == null) { - Permanent lki = (Permanent) game.getLastKnownInformation(source.getSourceId(), Zone.BATTLEFIELD); - if (lki != null) { - amountCounters = lki.getCounters().getCount(MUSTER_COUNTER_NAME); - } - } else { - new AddCountersSourceEffect(new Counter(MUSTER_COUNTER_NAME),false).apply(game, source); - amountCounters = sourcePermanent.getCounters().getCount(MUSTER_COUNTER_NAME); - - } - if (amountCounters > 0) { - return new CreateTokenEffect(new SoldierToken(), amountCounters).apply(game, source); - } - return false; - } -} diff --git a/Mage.Sets/src/mage/sets/gatecrash/SunhomeGuildmage.java b/Mage.Sets/src/mage/sets/gatecrash/SunhomeGuildmage.java index 0adc3c7a3a..4930c6e8ef 100644 --- a/Mage.Sets/src/mage/sets/gatecrash/SunhomeGuildmage.java +++ b/Mage.Sets/src/mage/sets/gatecrash/SunhomeGuildmage.java @@ -34,13 +34,12 @@ import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.continuous.BoostControlledEffect; -import mage.abilities.keyword.HasteAbility; import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Rarity; import mage.constants.Zone; -import mage.game.permanent.token.Token; +import mage.game.permanent.token.SoldierTokenWithHaste; /** * @@ -54,17 +53,14 @@ public class SunhomeGuildmage extends CardImpl { this.subtype.add("Human"); this.subtype.add("Wizard"); - this.power = new MageInt(2); this.toughness = new MageInt(2); - //{1}{R}{W}: Creatures you control get +1/+0 until end of turn. this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostControlledEffect(1, 0, Duration.EndOfTurn), new ManaCostsImpl("{1}{R}{W}"))); - + //{2}{R}{W}: Put a 1/1 red and white Soldier creature token with haste onto the battlefield. - this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new SoldierToken()), new ManaCostsImpl("{2}{R}{W}"))); - + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new SoldierTokenWithHaste()), new ManaCostsImpl("{2}{R}{W}"))); } public SunhomeGuildmage(final SunhomeGuildmage card) { @@ -76,20 +72,3 @@ public class SunhomeGuildmage extends CardImpl { return new SunhomeGuildmage(this); } } - - -class SoldierToken extends Token { - - public SoldierToken() { - super("Soldier", "1/1 red and white Soldier creature token with haste"); - cardType.add(CardType.CREATURE); - color.setWhite(true); - color.setRed(true); - subtype.add("Soldier"); - power = new MageInt(1); - toughness = new MageInt(1); - - this.addAbility(HasteAbility.getInstance()); - } - -} diff --git a/Mage/src/mage/counters/CounterType.java b/Mage/src/mage/counters/CounterType.java index 52ebd73221..3f952c8ef9 100644 --- a/Mage/src/mage/counters/CounterType.java +++ b/Mage/src/mage/counters/CounterType.java @@ -71,6 +71,7 @@ public enum CounterType { M1M1(new BoostCounter(-1, -1).name), M2M2(new BoostCounter(-2, -2).name), MINING("mining"), + MUSTER("muster"), P1P0(new BoostCounter(1, 0).name), P1P1(new BoostCounter(1, 1).name), P2P2(new BoostCounter(2, 2).name), diff --git a/Mage/src/mage/game/permanent/token/SoldierTokenWithHaste.java b/Mage/src/mage/game/permanent/token/SoldierTokenWithHaste.java new file mode 100644 index 0000000000..221ac747a7 --- /dev/null +++ b/Mage/src/mage/game/permanent/token/SoldierTokenWithHaste.java @@ -0,0 +1,53 @@ +/* +* 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.game.permanent.token; + +import java.util.Arrays; +import mage.constants.CardType; +import mage.MageInt; +import mage.abilities.keyword.HasteAbility; + +/** + * + * @author LoneFox + */ +public class SoldierTokenWithHaste extends Token { + + public SoldierTokenWithHaste() { + super("Soldier", "1/1 red and white Soldier creature token with haste"); + cardType.add(CardType.CREATURE); + color.setWhite(true); + color.setRed(true); + subtype.add("Soldier"); + power = new MageInt(1); + toughness = new MageInt(1); + addAbility(HasteAbility.getInstance()); + setOriginalExpansionSetCode("GTC"); + } +} From 54acb445db12390b0fae634382ca927a61687428 Mon Sep 17 00:00:00 2001 From: LoneFox Date: Sat, 26 Sep 2015 11:18:15 +0300 Subject: [PATCH 03/16] Add Goblin token with haste and use it for existing cards. Add missing images for Goblin token. --- .../mage/sets/khansoftarkir/Goblinslide.java | 20 +-------- .../sets/magic2015/GoblinRabblemaster.java | 20 +-------- .../newphyrexia/ChancellorOfTheForge.java | 19 ++------ .../sets/shardsofalara/GoblinAssault.java | 20 +-------- .../game/permanent/token/GoblinToken.java | 3 +- .../permanent/token/GoblinTokenWithHaste.java | 45 +++++++++++++++++++ 6 files changed, 56 insertions(+), 71 deletions(-) create mode 100644 Mage/src/mage/game/permanent/token/GoblinTokenWithHaste.java diff --git a/Mage.Sets/src/mage/sets/khansoftarkir/Goblinslide.java b/Mage.Sets/src/mage/sets/khansoftarkir/Goblinslide.java index 1effee12c3..75db169ba2 100644 --- a/Mage.Sets/src/mage/sets/khansoftarkir/Goblinslide.java +++ b/Mage.Sets/src/mage/sets/khansoftarkir/Goblinslide.java @@ -28,7 +28,6 @@ package mage.sets.khansoftarkir; import java.util.UUID; -import mage.MageInt; import mage.abilities.common.SpellCastControllerTriggeredAbility; import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.common.CreateTokenEffect; @@ -40,7 +39,7 @@ import mage.constants.Rarity; import mage.filter.FilterSpell; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.CardTypePredicate; -import mage.game.permanent.token.Token; +import mage.game.permanent.token.GoblinTokenWithHaste; /** * @@ -58,9 +57,8 @@ public class Goblinslide extends CardImpl { super(ownerId, 109, "Goblinslide", Rarity.UNCOMMON, new CardType[]{CardType.ENCHANTMENT}, "{2}{R}"); this.expansionSetCode = "KTK"; - // Whenever you cast a noncreature spell, you may pay {1}. If you do, put a 1/1 red Goblin creature token with haste onto the battlefield. - this.addAbility(new SpellCastControllerTriggeredAbility(new DoIfCostPaid(new CreateTokenEffect(new GoblinslideGoblinToken()), new GenericManaCost(1)), filter, false)); + this.addAbility(new SpellCastControllerTriggeredAbility(new DoIfCostPaid(new CreateTokenEffect(new GoblinTokenWithHaste()), new GenericManaCost(1)), filter, false)); } public Goblinslide(final Goblinslide card) { @@ -72,17 +70,3 @@ public class Goblinslide extends CardImpl { return new Goblinslide(this); } } - -class GoblinslideGoblinToken extends Token { - - GoblinslideGoblinToken() { - super("Goblin", "1/1 red Goblin creature token with haste"); - this.setOriginalExpansionSetCode("KTK"); - cardType.add(CardType.CREATURE); - subtype.add("Goblin"); - color.setRed(true); - power = new MageInt(1); - toughness = new MageInt(1); - addAbility(HasteAbility.getInstance()); - } -} diff --git a/Mage.Sets/src/mage/sets/magic2015/GoblinRabblemaster.java b/Mage.Sets/src/mage/sets/magic2015/GoblinRabblemaster.java index cf2df4c91f..44d241e528 100644 --- a/Mage.Sets/src/mage/sets/magic2015/GoblinRabblemaster.java +++ b/Mage.Sets/src/mage/sets/magic2015/GoblinRabblemaster.java @@ -38,7 +38,6 @@ import mage.abilities.effects.Effect; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.combat.AttacksIfAbleAllEffect; import mage.abilities.effects.common.continuous.BoostSourceEffect; -import mage.abilities.keyword.HasteAbility; import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Duration; @@ -49,7 +48,7 @@ import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.AnotherPredicate; import mage.filter.predicate.permanent.AttackingPredicate; import mage.filter.predicate.permanent.ControllerPredicate; -import mage.game.permanent.token.Token; +import mage.game.permanent.token.GoblinTokenWithHaste; import mage.watchers.common.AttackedThisTurnWatcher; /** @@ -83,7 +82,7 @@ public class GoblinRabblemaster extends CardImpl { this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect), new AttackedThisTurnWatcher()); // At the beginning of combat on your turn, put a 1/1 red Goblin creature token with haste onto the battlefield. - this.addAbility(new BeginningOfCombatTriggeredAbility(new CreateTokenEffect(new GoblinToken()), TargetController.YOU, false)); + this.addAbility(new BeginningOfCombatTriggeredAbility(new CreateTokenEffect(new GoblinTokenWithHaste()), TargetController.YOU, false)); // When Goblin Rabblemaster attacks, it gets +1/+0 until end of turn for each other attacking Goblin. this.addAbility(new AttacksTriggeredAbility(new BoostSourceEffect(new PermanentsOnBattlefieldCount(attackingFilter), new StaticValue(0), Duration.EndOfTurn, true), false)); @@ -98,18 +97,3 @@ public class GoblinRabblemaster extends CardImpl { return new GoblinRabblemaster(this); } } - -class GoblinToken extends Token { - - public GoblinToken() { - super("Goblin", "1/1 red Goblin creature token with haste"); - this.setOriginalExpansionSetCode("M15"); - cardType.add(CardType.CREATURE); - subtype.add("Goblin"); - color.setRed(true); - power = new MageInt(1); - toughness = new MageInt(1); - addAbility(HasteAbility.getInstance()); - } - -} diff --git a/Mage.Sets/src/mage/sets/newphyrexia/ChancellorOfTheForge.java b/Mage.Sets/src/mage/sets/newphyrexia/ChancellorOfTheForge.java index 581d267015..bda2d542c8 100644 --- a/Mage.Sets/src/mage/sets/newphyrexia/ChancellorOfTheForge.java +++ b/Mage.Sets/src/mage/sets/newphyrexia/ChancellorOfTheForge.java @@ -35,7 +35,6 @@ import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; import mage.abilities.effects.common.CreateTokenEffect; -import mage.abilities.keyword.HasteAbility; import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Rarity; @@ -45,7 +44,7 @@ import mage.filter.predicate.permanent.ControllerPredicate; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; -import mage.game.permanent.token.Token; +import mage.game.permanent.token.GoblinTokenWithHaste; /** * @@ -73,7 +72,7 @@ public class ChancellorOfTheForge extends CardImpl { // When Chancellor of the Forge enters the battlefield, put X 1/1 red Goblin creature tokens with haste onto the battlefield, where X is the number of creatures you control. DynamicValue value = new PermanentsOnBattlefieldCount(filter); - this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new GoblinToken(), value), false)); + this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new GoblinTokenWithHaste(), value), false)); } public ChancellorOfTheForge(final ChancellorOfTheForge card) { @@ -89,7 +88,7 @@ public class ChancellorOfTheForge extends CardImpl { class ChancellorOfTheForgeDelayedTriggeredAbility extends DelayedTriggeredAbility { ChancellorOfTheForgeDelayedTriggeredAbility () { - super(new CreateTokenEffect(new GoblinToken())); + super(new CreateTokenEffect(new GoblinTokenWithHaste())); } ChancellorOfTheForgeDelayedTriggeredAbility(ChancellorOfTheForgeDelayedTriggeredAbility ability) { @@ -110,15 +109,3 @@ class ChancellorOfTheForgeDelayedTriggeredAbility extends DelayedTriggeredAbilit return new ChancellorOfTheForgeDelayedTriggeredAbility(this); } } - -class GoblinToken extends Token { - public GoblinToken() { - super("Goblin", "1/1 red Goblin creature token with haste"); - cardType.add(CardType.CREATURE); - color.setRed(true); - subtype.add("Goblin"); - power = new MageInt(1); - toughness = new MageInt(1); - addAbility(HasteAbility.getInstance()); - } -} diff --git a/Mage.Sets/src/mage/sets/shardsofalara/GoblinAssault.java b/Mage.Sets/src/mage/sets/shardsofalara/GoblinAssault.java index 7877a087dc..9cd15845e5 100644 --- a/Mage.Sets/src/mage/sets/shardsofalara/GoblinAssault.java +++ b/Mage.Sets/src/mage/sets/shardsofalara/GoblinAssault.java @@ -28,12 +28,10 @@ package mage.sets.shardsofalara; import java.util.UUID; -import mage.MageInt; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.combat.AttacksIfAbleAllEffect; -import mage.abilities.keyword.HasteAbility; import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Duration; @@ -42,7 +40,7 @@ import mage.constants.TargetController; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.SubtypePredicate; -import mage.game.permanent.token.Token; +import mage.game.permanent.token.GoblinTokenWithHaste; import mage.watchers.common.AttackedThisTurnWatcher; /** @@ -62,7 +60,7 @@ public class GoblinAssault extends CardImpl { this.expansionSetCode = "ALA"; // At the beginning of your upkeep, put a 1/1 red Goblin creature token with haste onto the battlefield. - this.addAbility(new BeginningOfUpkeepTriggeredAbility(new CreateTokenEffect(new GoblinAssaultToken()), TargetController.YOU, false)); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new CreateTokenEffect(new GoblinTokenWithHaste()), TargetController.YOU, false)); // Goblin creatures attack each turn if able. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new AttacksIfAbleAllEffect(filter, Duration.WhileOnBattlefield)), new AttackedThisTurnWatcher()); @@ -77,17 +75,3 @@ public class GoblinAssault extends CardImpl { return new GoblinAssault(this); } } - -class GoblinAssaultToken extends Token { - - public GoblinAssaultToken() { - super("Goblin", "1/1 red Goblin creature token with haste"); - cardType.add(CardType.CREATURE); - subtype.add("Goblin"); - - color.setRed(true); - power = new MageInt(1); - toughness = new MageInt(1); - this.addAbility(HasteAbility.getInstance()); - } -} diff --git a/Mage/src/mage/game/permanent/token/GoblinToken.java b/Mage/src/mage/game/permanent/token/GoblinToken.java index 7b2dfd151f..798fdae0f8 100644 --- a/Mage/src/mage/game/permanent/token/GoblinToken.java +++ b/Mage/src/mage/game/permanent/token/GoblinToken.java @@ -39,7 +39,8 @@ public class GoblinToken extends Token { public GoblinToken() { super("Goblin", "1/1 red Goblin creature token"); - availableImageSetCodes.addAll(Arrays.asList("SOM", "M10", "C14", "KTK", "EVG", "DTK", "ORI", "DDG")); + availableImageSetCodes.addAll(Arrays.asList("10E", "ALA", "SOM", "M10", "NPH", "M13", "RTR", + "MMA", "M15", "C14", "KTK", "EVG", "DTK", "ORI", "DDG", "DDN")); cardType.add(CardType.CREATURE); subtype.add("Goblin"); diff --git a/Mage/src/mage/game/permanent/token/GoblinTokenWithHaste.java b/Mage/src/mage/game/permanent/token/GoblinTokenWithHaste.java new file mode 100644 index 0000000000..2e77c7a344 --- /dev/null +++ b/Mage/src/mage/game/permanent/token/GoblinTokenWithHaste.java @@ -0,0 +1,45 @@ +/* +* 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.game.permanent.token; + +import mage.abilities.keyword.HasteAbility; + +/** + * + * @author LoneFox + */ + +// Currently there are no separate images for this, let's use the same ones as the regular Goblin token. +public class GoblinTokenWithHaste extends GoblinToken { + + public GoblinTokenWithHaste() { + super(); + addAbility(HasteAbility.getInstance()); + } +} From 4e5bcddd56e76f151d7d5a975cfeda07a7b15b46 Mon Sep 17 00:00:00 2001 From: LoneFox Date: Sat, 26 Sep 2015 11:44:03 +0300 Subject: [PATCH 04/16] Add 5/5 Dragon token and use it for existing cards. --- .../mage/sets/commander/DeathByDragons.java | 20 +------ .../mage/sets/scourge/DayOfTheDragons.java | 25 +++------ .../mage/sets/tenthedition/DragonRoost.java | 22 ++------ .../sets/worldwake/DragonmasterOutcast.java | 18 +------ .../game/permanent/token/DragonToken2.java | 52 +++++++++++++++++++ 5 files changed, 66 insertions(+), 71 deletions(-) create mode 100644 Mage/src/mage/game/permanent/token/DragonToken2.java diff --git a/Mage.Sets/src/mage/sets/commander/DeathByDragons.java b/Mage.Sets/src/mage/sets/commander/DeathByDragons.java index b949893334..60572acafe 100644 --- a/Mage.Sets/src/mage/sets/commander/DeathByDragons.java +++ b/Mage.Sets/src/mage/sets/commander/DeathByDragons.java @@ -28,16 +28,15 @@ package mage.sets.commander; import java.util.UUID; -import mage.MageInt; import mage.ObjectColor; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; -import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.Rarity; import mage.game.Game; +import mage.game.permanent.token.DragonToken2; import mage.game.permanent.token.Token; import mage.players.Player; import mage.target.TargetPlayer; @@ -90,7 +89,7 @@ class DeathByDragonsEffect extends OneShotEffect { if (controller != null) { for (UUID playerId : controller.getInRange()) { if (!playerId.equals(this.getTargetPointer().getFirst(game, source))) { - Token token = new DragonToken(); + Token token = new DragonToken2(); token.putOntoBattlefield(1, game, source.getSourceId(), playerId); } } @@ -99,18 +98,3 @@ class DeathByDragonsEffect extends OneShotEffect { return false; } } - -class DragonToken extends Token { - - public DragonToken() { - super("Dragon", "5/5 red Dragon creature token with flying"); - cardType.add(CardType.CREATURE); - color.setRed(true); - subtype.add("Dragon"); - power = new MageInt(5); - toughness = new MageInt(5); - addAbility(FlyingAbility.getInstance()); - // set a set with correct token image - this.setOriginalExpansionSetCode("WWK"); - } -} diff --git a/Mage.Sets/src/mage/sets/scourge/DayOfTheDragons.java b/Mage.Sets/src/mage/sets/scourge/DayOfTheDragons.java index 4c442ac361..8ce0107426 100644 --- a/Mage.Sets/src/mage/sets/scourge/DayOfTheDragons.java +++ b/Mage.Sets/src/mage/sets/scourge/DayOfTheDragons.java @@ -28,17 +28,19 @@ package mage.sets.scourge; import java.util.UUID; - -import mage.constants.*; import mage.MageInt; import mage.ObjectColor; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.LeavesBattlefieldTriggeredAbility; import mage.abilities.effects.OneShotEffect; -import mage.abilities.keyword.FlyingAbility; import mage.cards.Card; 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.filter.FilterPermanent; import mage.filter.predicate.mageobject.CardTypePredicate; import mage.filter.predicate.mageobject.SubtypePredicate; @@ -46,7 +48,7 @@ import mage.filter.predicate.permanent.ControllerPredicate; import mage.game.ExileZone; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.game.permanent.token.Token; +import mage.game.permanent.token.DragonToken2; /** * @@ -106,7 +108,7 @@ class DayOfTheDragonsEntersEffect extends OneShotEffect { } } } - DragonToken token = new DragonToken(); + DragonToken2 token = new DragonToken2(); token.putOntoBattlefield(creaturesExiled, game, source.getSourceId(), source.getControllerId()); return true; } @@ -163,16 +165,3 @@ class DayOfTheDragonsLeavesEffect extends OneShotEffect { return new DayOfTheDragonsLeavesEffect(this); } } - -class DragonToken extends Token { - - public DragonToken() { - super("Dragon", "5/5 red Dragon creature token with flying"); - cardType.add(CardType.CREATURE); - color.setRed(true); - subtype.add("Dragon"); - power = new MageInt(5); - toughness = new MageInt(5); - addAbility(FlyingAbility.getInstance()); - } -} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/tenthedition/DragonRoost.java b/Mage.Sets/src/mage/sets/tenthedition/DragonRoost.java index 1fbc6d5c43..cdc462101f 100644 --- a/Mage.Sets/src/mage/sets/tenthedition/DragonRoost.java +++ b/Mage.Sets/src/mage/sets/tenthedition/DragonRoost.java @@ -28,18 +28,15 @@ package mage.sets.tenthedition; import java.util.UUID; - -import mage.constants.CardType; -import mage.constants.Rarity; -import mage.MageInt; import mage.ObjectColor; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.common.CreateTokenEffect; -import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; import mage.constants.Zone; -import mage.game.permanent.token.Token; +import mage.game.permanent.token.DragonToken2; /** * @@ -63,16 +60,3 @@ public class DragonRoost extends CardImpl { return new DragonRoost(this); } } - -class DragonToken2 extends Token { - DragonToken2() { - super("Dragon", "5/5 red Dragon creature token with flying"); - cardType.add(CardType.CREATURE); - color.setRed(true); - subtype.add("Dragon"); - power = new MageInt(5); - toughness = new MageInt(5); - addAbility(FlyingAbility.getInstance()); - } -} - diff --git a/Mage.Sets/src/mage/sets/worldwake/DragonmasterOutcast.java b/Mage.Sets/src/mage/sets/worldwake/DragonmasterOutcast.java index e0c43a32e0..b92c0b3227 100644 --- a/Mage.Sets/src/mage/sets/worldwake/DragonmasterOutcast.java +++ b/Mage.Sets/src/mage/sets/worldwake/DragonmasterOutcast.java @@ -38,12 +38,11 @@ import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; import mage.abilities.decorator.ConditionalTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; -import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.constants.TargetController; import mage.filter.FilterPermanent; import mage.filter.predicate.mageobject.CardTypePredicate; -import mage.game.permanent.token.Token; +import mage.game.permanent.token.DragonToken2; /** * @@ -67,7 +66,7 @@ public class DragonmasterOutcast extends CardImpl { this.toughness = new MageInt(1); // At the beginning of your upkeep, if you control six or more lands, put a 5/5 red Dragon creature token with flying onto the battlefield. - TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new CreateTokenEffect(new DragonToken(), 1), TargetController.YOU, false); + TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new CreateTokenEffect(new DragonToken2(), 1), TargetController.YOU, false); this.addAbility(new ConditionalTriggeredAbility(ability, new PermanentsOnTheBattlefieldCondition(filter, PermanentsOnTheBattlefieldCondition.CountType.MORE_THAN, 5), "At the beginning of your upkeep, if you control six or more lands, put a 5/5 red Dragon creature token with flying onto the battlefield.")); } @@ -80,16 +79,3 @@ public class DragonmasterOutcast extends CardImpl { return new DragonmasterOutcast(this); } } - -class DragonToken extends Token { - - public DragonToken() { - super("Dragon", "5/5 red Dragon creature token with flying"); - cardType.add(CardType.CREATURE); - color.setRed(true); - subtype.add("Dragon"); - power = new MageInt(5); - toughness = new MageInt(5); - addAbility(FlyingAbility.getInstance()); - } -} diff --git a/Mage/src/mage/game/permanent/token/DragonToken2.java b/Mage/src/mage/game/permanent/token/DragonToken2.java new file mode 100644 index 0000000000..5bf0ca7c0b --- /dev/null +++ b/Mage/src/mage/game/permanent/token/DragonToken2.java @@ -0,0 +1,52 @@ +/* +* 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.game.permanent.token; + +import java.util.Arrays; +import mage.constants.CardType; +import mage.MageInt; +import mage.abilities.keyword.FlyingAbility; + +/** + * + * @author LoneFox + */ +public class DragonToken2 extends Token { + + public DragonToken2() { + super("Dragon", "5/5 red Dragon creature token with flying"); + cardType.add(CardType.CREATURE); + color.setWhite(true); + subtype.add("Dragon"); + power = new MageInt(5); + toughness = new MageInt(5); + addAbility(FlyingAbility.getInstance()); + availableImageSetCodes.addAll(Arrays.asList("WWK", "10E")); + } +} From b64c49521240bf51d6272e329b7680f0601109dc Mon Sep 17 00:00:00 2001 From: LoneFox Date: Sat, 26 Sep 2015 11:44:59 +0300 Subject: [PATCH 05/16] Fix a copy-paste error --- Mage/src/mage/game/permanent/token/DragonToken2.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mage/src/mage/game/permanent/token/DragonToken2.java b/Mage/src/mage/game/permanent/token/DragonToken2.java index 5bf0ca7c0b..578178c9a6 100644 --- a/Mage/src/mage/game/permanent/token/DragonToken2.java +++ b/Mage/src/mage/game/permanent/token/DragonToken2.java @@ -42,7 +42,7 @@ public class DragonToken2 extends Token { public DragonToken2() { super("Dragon", "5/5 red Dragon creature token with flying"); cardType.add(CardType.CREATURE); - color.setWhite(true); + color.setRed(true); subtype.add("Dragon"); power = new MageInt(5); toughness = new MageInt(5); From e16bec3472672550393bf750163e26b2166f5e7d Mon Sep 17 00:00:00 2001 From: LoneFox Date: Sat, 26 Sep 2015 11:50:41 +0300 Subject: [PATCH 06/16] Add 5/5 Wurm token with trample and use it for existing cards. --- .../sets/dragonsmaze/AdventOfTheWurm.java | 24 +-------- .../mage/sets/returntoravnica/ArmadaWurm.java | 18 +------ .../sets/returntoravnica/WorldspineWurm.java | 22 ++------ .../mage/game/permanent/token/WurmToken2.java | 52 +++++++++++++++++++ 4 files changed, 60 insertions(+), 56 deletions(-) create mode 100644 Mage/src/mage/game/permanent/token/WurmToken2.java diff --git a/Mage.Sets/src/mage/sets/dragonsmaze/AdventOfTheWurm.java b/Mage.Sets/src/mage/sets/dragonsmaze/AdventOfTheWurm.java index c23ec62ddf..16eb3ddf20 100644 --- a/Mage.Sets/src/mage/sets/dragonsmaze/AdventOfTheWurm.java +++ b/Mage.Sets/src/mage/sets/dragonsmaze/AdventOfTheWurm.java @@ -29,14 +29,12 @@ package mage.sets.dragonsmaze; import java.util.UUID; -import mage.MageInt; import mage.ObjectColor; import mage.abilities.effects.common.CreateTokenEffect; -import mage.abilities.keyword.TrampleAbility; import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Rarity; -import mage.game.permanent.token.Token; +import mage.game.permanent.token.WurmToken2; /** * @@ -50,9 +48,8 @@ public class AdventOfTheWurm extends CardImpl { super(ownerId, 51, "Advent of the Wurm", Rarity.RARE, new CardType[]{CardType.INSTANT}, "{1}{G}{G}{W}"); this.expansionSetCode = "DGM"; - // Put a 5/5 green Wurm creature token with trample onto the battlefield. - this.getSpellAbility().addEffect(new CreateTokenEffect(new WurmToken())); + this.getSpellAbility().addEffect(new CreateTokenEffect(new WurmToken2())); } public AdventOfTheWurm(final AdventOfTheWurm card) { @@ -63,21 +60,4 @@ public class AdventOfTheWurm extends CardImpl { public AdventOfTheWurm copy() { return new AdventOfTheWurm(this); } - - private class WurmToken extends Token { - - private WurmToken() { - super("Wurm", "5/5 green Wurm creature token with trample"); - cardType.add(CardType.CREATURE); - color.setGreen(true); - subtype.add("Wurm"); - power = new MageInt(5); - toughness = new MageInt(5); - - addAbility(TrampleAbility.getInstance()); - // for image - setOriginalExpansionSetCode("RTR"); - } - - } } diff --git a/Mage.Sets/src/mage/sets/returntoravnica/ArmadaWurm.java b/Mage.Sets/src/mage/sets/returntoravnica/ArmadaWurm.java index 4aa5f82ae2..dc031cefc9 100644 --- a/Mage.Sets/src/mage/sets/returntoravnica/ArmadaWurm.java +++ b/Mage.Sets/src/mage/sets/returntoravnica/ArmadaWurm.java @@ -38,7 +38,7 @@ import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.keyword.TrampleAbility; import mage.cards.CardImpl; -import mage.game.permanent.token.Token; +import mage.game.permanent.token.WurmToken2; /** * @@ -59,7 +59,7 @@ public class ArmadaWurm extends CardImpl { this.addAbility(TrampleAbility.getInstance()); // When Armada Wurm enters the battlefield, put a 5/5 green Wurm creature token with trample onto the battlefield. - this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new ArmadaWurmToken()), false)); + this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new WurmToken2()), false)); } @@ -71,18 +71,4 @@ public class ArmadaWurm extends CardImpl { public ArmadaWurm copy() { return new ArmadaWurm(this); } - - private class ArmadaWurmToken extends Token { - - private ArmadaWurmToken() { - super("Wurm", "a 5/5 green Wurm creature token with trample"); - cardType.add(CardType.CREATURE); - color.setGreen(true); - subtype.add("Wurm"); - power = new MageInt(5); - toughness = new MageInt(5); - addAbility(TrampleAbility.getInstance()); - } - - } } diff --git a/Mage.Sets/src/mage/sets/returntoravnica/WorldspineWurm.java b/Mage.Sets/src/mage/sets/returntoravnica/WorldspineWurm.java index a2927db338..33d9e8cd31 100644 --- a/Mage.Sets/src/mage/sets/returntoravnica/WorldspineWurm.java +++ b/Mage.Sets/src/mage/sets/returntoravnica/WorldspineWurm.java @@ -37,7 +37,7 @@ import mage.abilities.keyword.TrampleAbility; import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Rarity; -import mage.game.permanent.token.Token; +import mage.game.permanent.token.WurmToken2; /** * @@ -55,10 +55,10 @@ public class WorldspineWurm extends CardImpl { // Trample this.addAbility(TrampleAbility.getInstance()); - + // When Worldspine Wurm dies, put three 5/5 green Wurm creature tokens with trample onto the battlefield. - this.addAbility(new DiesTriggeredAbility(new CreateTokenEffect(new WorldspineWurmToken(), 3))); - + this.addAbility(new DiesTriggeredAbility(new CreateTokenEffect(new WurmToken2(), 3))); + // When Worldspine Wurm is put into a graveyard from anywhere, shuffle it into its owner's library. this.addAbility(new PutIntoGraveFromAnywhereSourceTriggeredAbility(new ShuffleIntoLibrarySourceEffect())); } @@ -72,17 +72,3 @@ public class WorldspineWurm extends CardImpl { return new WorldspineWurm(this); } } - -class WorldspineWurmToken extends Token { - - public WorldspineWurmToken() { - super("Wurm", "5/5 green Wurm creature tokens with trample"); - cardType.add(CardType.CREATURE); - color.setGreen(true); - subtype.add("Wurm"); - power = new MageInt(5); - toughness = new MageInt(5); - - this.addAbility(TrampleAbility.getInstance()); - } -} \ No newline at end of file diff --git a/Mage/src/mage/game/permanent/token/WurmToken2.java b/Mage/src/mage/game/permanent/token/WurmToken2.java new file mode 100644 index 0000000000..3cbdcca28e --- /dev/null +++ b/Mage/src/mage/game/permanent/token/WurmToken2.java @@ -0,0 +1,52 @@ +/* +* 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.game.permanent.token; + +import java.util.Arrays; +import mage.constants.CardType; +import mage.MageInt; +import mage.abilities.keyword.TrampleAbility; + +/** + * + * @author LoneFox + */ +public class WurmToken2 extends Token { + + public WurmToken2() { + super("Wurm", "5/5 green Wurm creature token with trample"); + cardType.add(CardType.CREATURE); + color.setGreen(true); + subtype.add("Wurm"); + power = new MageInt(5); + toughness = new MageInt(5); + addAbility(TrampleAbility.getInstance()); + setOriginalExpansionSetCode("RTR"); + } +} From c47d39390f4e2c14a5912278646ea1522f609b36 Mon Sep 17 00:00:00 2001 From: LoneFox Date: Sat, 26 Sep 2015 12:09:00 +0300 Subject: [PATCH 07/16] Add 4/4 Beast token and use it for existing cards. --- .../src/mage/sets/odyssey/BeastAttack.java | 23 +------ .../src/mage/sets/scourge/HuntingPack.java | 19 +----- .../mage/sets/zendikar/BalothCageTrap.java | 22 ++---- .../mage/sets/zendikar/RampagingBaloths.java | 30 +++------ .../game/permanent/token/BeastToken2.java | 67 +++++++++++++++++++ 5 files changed, 85 insertions(+), 76 deletions(-) create mode 100644 Mage/src/mage/game/permanent/token/BeastToken2.java diff --git a/Mage.Sets/src/mage/sets/odyssey/BeastAttack.java b/Mage.Sets/src/mage/sets/odyssey/BeastAttack.java index d0b535fcdd..750cf41552 100644 --- a/Mage.Sets/src/mage/sets/odyssey/BeastAttack.java +++ b/Mage.Sets/src/mage/sets/odyssey/BeastAttack.java @@ -28,7 +28,6 @@ package mage.sets.odyssey; import java.util.UUID; -import mage.MageInt; import mage.ObjectColor; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.common.CreateTokenEffect; @@ -37,7 +36,7 @@ import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Rarity; import mage.constants.TimingRule; -import mage.game.permanent.token.Token; +import mage.game.permanent.token.BeastToken2; /** * @@ -49,10 +48,9 @@ public class BeastAttack extends CardImpl { super(ownerId, 230, "Beast Attack", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{2}{G}{G}{G}"); this.expansionSetCode = "ODY"; - // Put a 4/4 green Beast creature token onto the battlefield. - this.getSpellAbility().addEffect(new CreateTokenEffect(new BeastToken_44())); - + this.getSpellAbility().addEffect(new CreateTokenEffect(new BeastToken2())); + // Flashback {2}{G}{G}{G} this.addAbility(new FlashbackAbility(new ManaCostsImpl("{2}{G}{G}{G}"), TimingRule.INSTANT)); } @@ -66,18 +64,3 @@ public class BeastAttack extends CardImpl { return new BeastAttack(this); } } - -class BeastToken_44 extends Token { - - public BeastToken_44() { - super("Beast", "4/4 green Beast creature token"); - cardType.add(CardType.CREATURE); - color.setGreen(true); - subtype.add("Beast"); - power = new MageInt(4); - toughness = new MageInt(4); - // to get an image for the token - this.setOriginalExpansionSetCode("ZEN"); - } - -} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/scourge/HuntingPack.java b/Mage.Sets/src/mage/sets/scourge/HuntingPack.java index f099f4f25f..81e75636f1 100644 --- a/Mage.Sets/src/mage/sets/scourge/HuntingPack.java +++ b/Mage.Sets/src/mage/sets/scourge/HuntingPack.java @@ -30,12 +30,10 @@ package mage.sets.scourge; import java.util.UUID; import mage.constants.CardType; import mage.constants.Rarity; -import mage.MageInt; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.keyword.StormAbility; import mage.cards.CardImpl; -import mage.game.permanent.token.Token; - +import mage.game.permanent.token.BeastToken2; /** * @@ -47,9 +45,8 @@ public class HuntingPack extends CardImpl { super(ownerId, 121, "Hunting Pack", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{5}{G}{G}"); this.expansionSetCode = "SCG"; - // Put a 4/4 green Beast creature token onto the battlefield. - this.getSpellAbility().addEffect(new CreateTokenEffect(new HuntingPackToken(), 1)); + this.getSpellAbility().addEffect(new CreateTokenEffect(new BeastToken2(), 1)); // Storm this.addAbility(new StormAbility()); } @@ -63,15 +60,3 @@ public class HuntingPack extends CardImpl { return new HuntingPack(this); } } - -class HuntingPackToken extends Token { - - public HuntingPackToken() { - super("Beast", "4/4 green Beast creature token"); - cardType.add(CardType.CREATURE); - subtype.add("Beast"); - this.color.setGreen(true); - power = new MageInt(4); - toughness = new MageInt(4); - } -} diff --git a/Mage.Sets/src/mage/sets/zendikar/BalothCageTrap.java b/Mage.Sets/src/mage/sets/zendikar/BalothCageTrap.java index 62210c8396..74f2f9c663 100644 --- a/Mage.Sets/src/mage/sets/zendikar/BalothCageTrap.java +++ b/Mage.Sets/src/mage/sets/zendikar/BalothCageTrap.java @@ -28,21 +28,19 @@ package mage.sets.zendikar; import java.util.UUID; - -import mage.constants.CardType; -import mage.constants.Rarity; -import mage.MageInt; import mage.ObjectColor; import mage.abilities.Ability; import mage.abilities.costs.AlternativeCostImpl; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.common.CreateTokenEffect; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; import mage.constants.WatcherScope; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; -import mage.game.permanent.token.Token; +import mage.game.permanent.token.BeastToken2; import mage.watchers.Watcher; /** @@ -62,7 +60,7 @@ public class BalothCageTrap extends CardImpl { this.getSpellAbility().addWatcher(new BalothCageTrapWatcher()); // Put a 4/4 green Beast creature token onto the battlefield. - this.getSpellAbility().addEffect(new CreateTokenEffect(new BeastGreenToken())); + this.getSpellAbility().addEffect(new CreateTokenEffect(new BeastToken2())); } public BalothCageTrap(final BalothCageTrap card) { @@ -140,15 +138,3 @@ class BalothCageTrapAlternativeCost extends AlternativeCostImpl { return "If an opponent had an artifact enter the battlefield under his or her control this turn, you may pay {1}{G} rather than pay Baloth Cage Trap's mana cost"; } } - -class BeastGreenToken extends Token { - - public BeastGreenToken() { - super("Beast", "4/4 green Beast creature token"); - cardType.add(CardType.CREATURE); - color.setGreen(true); - subtype.add("Beast"); - power = new MageInt(4); - toughness = new MageInt(4); - } -} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/zendikar/RampagingBaloths.java b/Mage.Sets/src/mage/sets/zendikar/RampagingBaloths.java index 7a721a310f..488ab7bde1 100644 --- a/Mage.Sets/src/mage/sets/zendikar/RampagingBaloths.java +++ b/Mage.Sets/src/mage/sets/zendikar/RampagingBaloths.java @@ -1,16 +1,16 @@ /* * 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 @@ -20,7 +20,7 @@ * 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. @@ -29,14 +29,14 @@ package mage.sets.zendikar; import java.util.UUID; -import mage.constants.CardType; -import mage.constants.Rarity; import mage.MageInt; import mage.abilities.common.LandfallAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.keyword.TrampleAbility; import mage.cards.CardImpl; -import mage.game.permanent.token.Token; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.game.permanent.token.BeastToken2; /** * @@ -52,7 +52,7 @@ public class RampagingBaloths extends CardImpl { this.power = new MageInt(6); this.toughness = new MageInt(6); this.addAbility(TrampleAbility.getInstance()); - this.addAbility(new LandfallAbility(new CreateTokenEffect(new RampagingBalothsToken()), true)); + this.addAbility(new LandfallAbility(new CreateTokenEffect(new BeastToken2()), true)); } public RampagingBaloths(final RampagingBaloths card) { @@ -65,15 +65,3 @@ public class RampagingBaloths extends CardImpl { } } - -class RampagingBalothsToken extends Token { - - public RampagingBalothsToken() { - super("Beast", "4/4 green Beast creature token"); - cardType.add(CardType.CREATURE); - subtype.add("Beast"); - this.color.setGreen(true); - power = new MageInt(4); - toughness = new MageInt(4); - } -} \ No newline at end of file diff --git a/Mage/src/mage/game/permanent/token/BeastToken2.java b/Mage/src/mage/game/permanent/token/BeastToken2.java new file mode 100644 index 0000000000..57b22f20eb --- /dev/null +++ b/Mage/src/mage/game/permanent/token/BeastToken2.java @@ -0,0 +1,67 @@ +/* +* 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.game.permanent.token; + +import java.util.Arrays; +import mage.constants.CardType; +import mage.MageInt; + +/** + * + * @author LoneFox + */ +public class BeastToken2 extends Token { + + public BeastToken2() { + super("Beast", "4/4 green Beast creature token"); + cardType.add(CardType.CREATURE); + color.setGreen(true); + subtype.add("Beast"); + power = new MageInt(4); + toughness = new MageInt(4); + availableImageSetCodes.addAll(Arrays.asList("ZEN", "C14", "DDD")); + } + + public BeastToken2(final BeastToken2 token) { + super(token); + } + + @Override + public BeastToken2 copy() { + return new BeastToken2(this); + } + + @Override + public void setExpansionSetCodeForImage(String code) { + super.setExpansionSetCodeForImage(code); + if(getOriginalExpansionSetCode().equals("C14") || getOriginalExpansionSetCode().equals("DDD")) { + this.setTokenType(2); + } + } +} From a2e1e2e614606e33ee3fd7935f19b8577125872b Mon Sep 17 00:00:00 2001 From: LoneFox Date: Sat, 26 Sep 2015 13:31:40 +0300 Subject: [PATCH 08/16] Remove some unneeded imports and fix an incorrect set code --- Mage/src/mage/game/permanent/token/SoldierTokenWithHaste.java | 1 - Mage/src/mage/game/permanent/token/ThopterColorlessToken.java | 2 +- Mage/src/mage/game/permanent/token/WurmToken2.java | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/Mage/src/mage/game/permanent/token/SoldierTokenWithHaste.java b/Mage/src/mage/game/permanent/token/SoldierTokenWithHaste.java index 221ac747a7..458310b2ef 100644 --- a/Mage/src/mage/game/permanent/token/SoldierTokenWithHaste.java +++ b/Mage/src/mage/game/permanent/token/SoldierTokenWithHaste.java @@ -28,7 +28,6 @@ package mage.game.permanent.token; -import java.util.Arrays; import mage.constants.CardType; import mage.MageInt; import mage.abilities.keyword.HasteAbility; diff --git a/Mage/src/mage/game/permanent/token/ThopterColorlessToken.java b/Mage/src/mage/game/permanent/token/ThopterColorlessToken.java index 840f15504b..695be8d111 100644 --- a/Mage/src/mage/game/permanent/token/ThopterColorlessToken.java +++ b/Mage/src/mage/game/permanent/token/ThopterColorlessToken.java @@ -44,7 +44,7 @@ public class ThopterColorlessToken extends Token { final static private List tokenImageSets = new ArrayList<>(); static { - tokenImageSets.addAll(Arrays.asList("EXO", "ORI")); + tokenImageSets.addAll(Arrays.asList("MBS", "ORI")); } public ThopterColorlessToken() { diff --git a/Mage/src/mage/game/permanent/token/WurmToken2.java b/Mage/src/mage/game/permanent/token/WurmToken2.java index 3cbdcca28e..e4b27e261d 100644 --- a/Mage/src/mage/game/permanent/token/WurmToken2.java +++ b/Mage/src/mage/game/permanent/token/WurmToken2.java @@ -28,7 +28,6 @@ package mage.game.permanent.token; -import java.util.Arrays; import mage.constants.CardType; import mage.MageInt; import mage.abilities.keyword.TrampleAbility; From 02d499c31779c0fe419b1be983c721854a4a0dc1 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Mon, 28 Sep 2015 17:19:03 +0200 Subject: [PATCH 09/16] Minor changes. --- .../mage/sets/morningtide/GiltLeafArchdruid.java | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/Mage.Sets/src/mage/sets/morningtide/GiltLeafArchdruid.java b/Mage.Sets/src/mage/sets/morningtide/GiltLeafArchdruid.java index 92e5ee86a5..4773cc926f 100644 --- a/Mage.Sets/src/mage/sets/morningtide/GiltLeafArchdruid.java +++ b/Mage.Sets/src/mage/sets/morningtide/GiltLeafArchdruid.java @@ -50,6 +50,7 @@ import mage.filter.common.FilterLandPermanent; import mage.filter.predicate.mageobject.SubtypePredicate; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.players.Player; import mage.target.TargetPlayer; import mage.target.common.TargetControlledCreaturePermanent; @@ -60,11 +61,11 @@ import mage.target.common.TargetControlledCreaturePermanent; public class GiltLeafArchdruid extends CardImpl { private static final FilterSpell filterSpell = new FilterSpell("a Druid spell"); - + static { filterSpell.add(new SubtypePredicate("Druid")); } - + public GiltLeafArchdruid(UUID ownerId) { super(ownerId, 124, "Gilt-Leaf Archdruid", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{3}{G}{G}"); this.expansionSetCode = "MOR"; @@ -76,6 +77,7 @@ public class GiltLeafArchdruid extends CardImpl { // Whenever you cast a Druid spell, you may draw a card. this.addAbility(new SpellCastControllerTriggeredAbility(new DrawCardSourceControllerEffect(1), filterSpell, true)); + // Tap seven untapped Druids you control: Gain control of all lands target player controls. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new GainControlAllLandsEffect(Duration.EndOfGame), new TapTargetCost(new TargetControlledCreaturePermanent(7, 7, new FilterControlledCreaturePermanent("Druid", "Druids you control"), true))); ability.addTarget(new TargetPlayer()); @@ -109,14 +111,17 @@ class GainControlAllLandsEffect extends ContinuousEffectImpl { @Override public boolean apply(Game game, Ability source) { - if (targetPointer != null) { - for(Permanent permanent : game.getBattlefield().getAllActivePermanents(new FilterLandPermanent(), targetPointer.getFirst(game, source), game)){ + Player targetPlayer = game.getPlayer(targetPointer.getFirst(game, source)); + if (targetPlayer != null && targetPlayer.isInGame()) { + for (Permanent permanent : game.getBattlefield().getAllActivePermanents(new FilterLandPermanent(), targetPointer.getFirst(game, source), game)) { if (permanent != null) { permanent.changeControllerId(source.getControllerId(), game); } } + } else { + discard(); } - return false; + return true; } @Override From 6d90539b7b43d6a5e90ebda7a36b3fc8ea68c800 Mon Sep 17 00:00:00 2001 From: LoneFox Date: Tue, 29 Sep 2015 12:19:50 +0300 Subject: [PATCH 10/16] Fix DealsDamageToOpponentTriggeredAbility unconditionally overwriting the targets of any effects added to it. This fixes at least Charnelhoard Wurm, and possibly other similar abilities. --- .../mage/sets/apocalypse/FungalShambler.java | 2 +- .../mage/sets/commander/HydraOmnivore.java | 2 +- .../src/mage/sets/legends/NicolBolas.java | 2 +- .../mage/sets/magic2010/HypnoticSpecter.java | 2 +- .../portalthreekingdoms/WeiNightRaiders.java | 2 +- .../ZhangLiaoHeroOfHefei.java | 2 +- ...DealsDamageToOpponentTriggeredAbility.java | 20 +++++++++++++------ 7 files changed, 20 insertions(+), 12 deletions(-) diff --git a/Mage.Sets/src/mage/sets/apocalypse/FungalShambler.java b/Mage.Sets/src/mage/sets/apocalypse/FungalShambler.java index 385de243c2..b9f0b5e9ec 100644 --- a/Mage.Sets/src/mage/sets/apocalypse/FungalShambler.java +++ b/Mage.Sets/src/mage/sets/apocalypse/FungalShambler.java @@ -58,7 +58,7 @@ public class FungalShambler extends CardImpl { // Whenever Fungal Shambler deals damage to an opponent, you draw a card and that opponent discards a card. Effect effect = new DrawCardSourceControllerEffect(1); effect.setText("you draw a card"); - Ability ability = new DealsDamageToOpponentTriggeredAbility(effect, false); + Ability ability = new DealsDamageToOpponentTriggeredAbility(effect, false, false, true); effect = new DiscardTargetEffect(1); effect.setText("and that opponent discards a card"); ability.addEffect(effect); diff --git a/Mage.Sets/src/mage/sets/commander/HydraOmnivore.java b/Mage.Sets/src/mage/sets/commander/HydraOmnivore.java index fea88abc3d..2f56264ff0 100644 --- a/Mage.Sets/src/mage/sets/commander/HydraOmnivore.java +++ b/Mage.Sets/src/mage/sets/commander/HydraOmnivore.java @@ -55,7 +55,7 @@ public class HydraOmnivore extends CardImpl { this.toughness = new MageInt(8); // Whenever Hydra Omnivore deals combat damage to an opponent, it deals that much damage to each other opponent. - this.addAbility(new DealsDamageToOpponentTriggeredAbility(new HydraOmnivoreEffect(), false, true)); + this.addAbility(new DealsDamageToOpponentTriggeredAbility(new HydraOmnivoreEffect(), false, true, true)); } public HydraOmnivore(final HydraOmnivore card) { diff --git a/Mage.Sets/src/mage/sets/legends/NicolBolas.java b/Mage.Sets/src/mage/sets/legends/NicolBolas.java index 8bf534631e..b53d646381 100644 --- a/Mage.Sets/src/mage/sets/legends/NicolBolas.java +++ b/Mage.Sets/src/mage/sets/legends/NicolBolas.java @@ -62,7 +62,7 @@ public class NicolBolas extends CardImpl { this.addAbility(new BeginningOfUpkeepTriggeredAbility(new SacrificeSourceUnlessPaysEffect(new ManaCostsImpl("{U}{B}{R}")), TargetController.YOU, false)); // Whenever Nicol Bolas deals damage to an opponent, that player discards his or her hand. - this.addAbility(new DealsDamageToOpponentTriggeredAbility(new DiscardHandTargetEffect("that player"), false)); + this.addAbility(new DealsDamageToOpponentTriggeredAbility(new DiscardHandTargetEffect("that player"), false, false, true)); } public NicolBolas(final NicolBolas card) { diff --git a/Mage.Sets/src/mage/sets/magic2010/HypnoticSpecter.java b/Mage.Sets/src/mage/sets/magic2010/HypnoticSpecter.java index e120011e38..7dcc9eda4e 100644 --- a/Mage.Sets/src/mage/sets/magic2010/HypnoticSpecter.java +++ b/Mage.Sets/src/mage/sets/magic2010/HypnoticSpecter.java @@ -54,7 +54,7 @@ public class HypnoticSpecter extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // Whenever Hypnotic Specter deals damage to an opponent, that player discards a card at random. - this.addAbility(new DealsDamageToOpponentTriggeredAbility(new DiscardTargetEffect(1, true))); + this.addAbility(new DealsDamageToOpponentTriggeredAbility(new DiscardTargetEffect(1, true), false, false, true)); } public HypnoticSpecter(final HypnoticSpecter card) { diff --git a/Mage.Sets/src/mage/sets/portalthreekingdoms/WeiNightRaiders.java b/Mage.Sets/src/mage/sets/portalthreekingdoms/WeiNightRaiders.java index 5b20e8e973..4d3b709a32 100644 --- a/Mage.Sets/src/mage/sets/portalthreekingdoms/WeiNightRaiders.java +++ b/Mage.Sets/src/mage/sets/portalthreekingdoms/WeiNightRaiders.java @@ -53,7 +53,7 @@ public class WeiNightRaiders extends CardImpl { // Horsemanship this.addAbility(HorsemanshipAbility.getInstance()); // Whenever Wei Night Raiders deals damage to an opponent, that player discards a card. - this.addAbility(new DealsDamageToOpponentTriggeredAbility(new DiscardTargetEffect(1), false)); + this.addAbility(new DealsDamageToOpponentTriggeredAbility(new DiscardTargetEffect(1), false, false, true)); } public WeiNightRaiders(final WeiNightRaiders card) { diff --git a/Mage.Sets/src/mage/sets/portalthreekingdoms/ZhangLiaoHeroOfHefei.java b/Mage.Sets/src/mage/sets/portalthreekingdoms/ZhangLiaoHeroOfHefei.java index 7d3cd94740..da66b3b4b9 100644 --- a/Mage.Sets/src/mage/sets/portalthreekingdoms/ZhangLiaoHeroOfHefei.java +++ b/Mage.Sets/src/mage/sets/portalthreekingdoms/ZhangLiaoHeroOfHefei.java @@ -51,7 +51,7 @@ public class ZhangLiaoHeroOfHefei extends CardImpl { this.toughness = new MageInt(3); // Whenever Zhang Liao, Hero of Hefei deals damage to an opponent, that opponent discards a card. - this.addAbility(new DealsDamageToOpponentTriggeredAbility(new DiscardTargetEffect(1), false)); + this.addAbility(new DealsDamageToOpponentTriggeredAbility(new DiscardTargetEffect(1), false, false, true)); } public ZhangLiaoHeroOfHefei(final ZhangLiaoHeroOfHefei card) { diff --git a/Mage/src/mage/abilities/common/DealsDamageToOpponentTriggeredAbility.java b/Mage/src/mage/abilities/common/DealsDamageToOpponentTriggeredAbility.java index 811b091401..3f9f5d30f0 100644 --- a/Mage/src/mage/abilities/common/DealsDamageToOpponentTriggeredAbility.java +++ b/Mage/src/mage/abilities/common/DealsDamageToOpponentTriggeredAbility.java @@ -40,24 +40,30 @@ import mage.target.targetpointer.FixedTarget; */ public class DealsDamageToOpponentTriggeredAbility extends TriggeredAbilityImpl { - boolean onlyCombat; + private final boolean onlyCombat, setTargetPointer; public DealsDamageToOpponentTriggeredAbility(Effect effect) { - this(effect, false, false); + this(effect, false, false, false); } public DealsDamageToOpponentTriggeredAbility(Effect effect, boolean optional) { - this(effect, optional, false); + this(effect, optional, false, false); } public DealsDamageToOpponentTriggeredAbility(Effect effect, boolean optional, boolean onlyCombat) { + this(effect, optional, onlyCombat, false); + } + + public DealsDamageToOpponentTriggeredAbility(Effect effect, boolean optional, boolean onlyCombat, boolean setTargetPointer) { super(Zone.BATTLEFIELD, effect, optional); this.onlyCombat = onlyCombat; + this.setTargetPointer = setTargetPointer; } public DealsDamageToOpponentTriggeredAbility(final DealsDamageToOpponentTriggeredAbility ability) { super(ability); this.onlyCombat = ability.onlyCombat; + this.setTargetPointer = ability.setTargetPointer; } @Override @@ -80,9 +86,11 @@ public class DealsDamageToOpponentTriggeredAbility extends TriggeredAbilityImpl return false; } } - for (Effect effect : getEffects()) { - effect.setTargetPointer(new FixedTarget(event.getTargetId())); - effect.setValue("damage", event.getAmount()); + if(setTargetPointer) { + for (Effect effect : getEffects()) { + effect.setTargetPointer(new FixedTarget(event.getTargetId())); + effect.setValue("damage", event.getAmount()); + } } return true; } From 82f2d73fb9978a2373f384c064c3cf4543d8e8f7 Mon Sep 17 00:00:00 2001 From: LoneFox Date: Tue, 29 Sep 2015 13:15:09 +0300 Subject: [PATCH 11/16] Add DontUntapAsLongAsSourceTappedEffect and connectSource parameter to TapTargetEffect. Use them for existing cards. Implement card: Thalakos Dreamsower --- .../journeyintonyx/DesertersQuarters.java | 88 +---------- .../src/mage/sets/mirage/AmberPrison.java | 138 +----------------- .../mage/sets/scarsofmirrodin/RustTick.java | 88 +---------- .../mage/sets/tempest/ThalakosDreamsower.java | 76 ++++++++++ .../DontUntapAsLongAsSourceTappedEffect.java | 78 ++++++++++ .../effects/common/TapTargetEffect.java | 31 +++- 6 files changed, 189 insertions(+), 310 deletions(-) create mode 100644 Mage.Sets/src/mage/sets/tempest/ThalakosDreamsower.java create mode 100644 Mage/src/mage/abilities/effects/common/DontUntapAsLongAsSourceTappedEffect.java diff --git a/Mage.Sets/src/mage/sets/journeyintonyx/DesertersQuarters.java b/Mage.Sets/src/mage/sets/journeyintonyx/DesertersQuarters.java index 41c34c3891..6604ae9340 100644 --- a/Mage.Sets/src/mage/sets/journeyintonyx/DesertersQuarters.java +++ b/Mage.Sets/src/mage/sets/journeyintonyx/DesertersQuarters.java @@ -29,21 +29,16 @@ package mage.sets.journeyintonyx; import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.Mode; import mage.abilities.common.SimpleActivatedAbility; -import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SkipUntapOptionalAbility; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.effects.RestrictionEffect; +import mage.abilities.effects.common.DontUntapAsLongAsSourceTappedEffect; import mage.abilities.effects.common.TapTargetEffect; import mage.cards.CardImpl; import mage.constants.CardType; -import mage.constants.Duration; import mage.constants.Rarity; import mage.constants.Zone; -import mage.game.Game; -import mage.game.permanent.Permanent; import mage.target.common.TargetCreaturePermanent; /** @@ -60,12 +55,11 @@ public class DesertersQuarters extends CardImpl { this.addAbility(new SkipUntapOptionalAbility()); // {6}, T: Tap target creature. It doesn't untap during its controller's untap step for as long as Deserter's Quarters remains tapped. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DesertersQuartersTapTargetEffect(), new GenericManaCost(6)); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TapTargetEffect(true), new GenericManaCost(6)); ability.addCost(new TapSourceCost()); ability.addTarget(new TargetCreaturePermanent()); + ability.addEffect(new DontUntapAsLongAsSourceTappedEffect()); this.addAbility(ability); - - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new DesertersQuartersRestrictionEffect())); } public DesertersQuarters(final DesertersQuarters card) { @@ -77,79 +71,3 @@ public class DesertersQuarters extends CardImpl { return new DesertersQuarters(this); } } - -class DesertersQuartersTapTargetEffect extends TapTargetEffect { - - public DesertersQuartersTapTargetEffect() { - super(); - staticText = "Tap target creature. It doesn't untap during its controller's untap step for as long as {this} remains tapped"; - } - - public DesertersQuartersTapTargetEffect(final DesertersQuartersTapTargetEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent sourcePermanent = game.getPermanent(source.getSourceId()); - if (sourcePermanent != null) { - sourcePermanent.clearConnectedCards("DesertersQuarters"); - } - for (UUID target : targetPointer.getTargets(game, source)) { - Permanent permanent = game.getPermanent(target); - if (sourcePermanent != null) { - sourcePermanent.addConnectedCard("DesertersQuarters", permanent.getId()); - } - if (permanent != null) { - permanent.tap(game); - } - } - return true; - } - - @Override - public DesertersQuartersTapTargetEffect copy() { - return new DesertersQuartersTapTargetEffect(this); - } - - @Override - public String getText(Mode mode) { - return staticText; - } -} - -class DesertersQuartersRestrictionEffect extends RestrictionEffect { - - public DesertersQuartersRestrictionEffect() { - super(Duration.WhileOnBattlefield); - } - - public DesertersQuartersRestrictionEffect(final DesertersQuartersRestrictionEffect effect) { - super(effect); - } - - @Override - public boolean applies(Permanent permanent, Ability source, Game game) { - Permanent rustTick = game.getPermanent(source.getSourceId()); - if (rustTick != null && rustTick.isTapped()) { - if (rustTick.getConnectedCards("DesertersQuarters").size() > 0) { - UUID target = rustTick.getConnectedCards("DesertersQuarters").get(0); - if (target != null && target.equals(permanent.getId())) { - return true; - } - } - } - return false; - } - - @Override - public boolean canBeUntapped(Permanent permanent, Ability source, Game game) { - return false; - } - - @Override - public DesertersQuartersRestrictionEffect copy() { - return new DesertersQuartersRestrictionEffect(this); - } - -} diff --git a/Mage.Sets/src/mage/sets/mirage/AmberPrison.java b/Mage.Sets/src/mage/sets/mirage/AmberPrison.java index 3653f69be8..4e1de790d6 100644 --- a/Mage.Sets/src/mage/sets/mirage/AmberPrison.java +++ b/Mage.Sets/src/mage/sets/mirage/AmberPrison.java @@ -29,27 +29,19 @@ package mage.sets.mirage; import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.SimpleActivatedAbility; -import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SkipUntapOptionalAbility; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.RestrictionEffect; +import mage.abilities.effects.common.DontUntapAsLongAsSourceTappedEffect; +import mage.abilities.effects.common.TapTargetEffect; import mage.cards.CardImpl; import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Outcome; import mage.constants.Rarity; import mage.constants.Zone; import mage.filter.FilterPermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.CardTypePredicate; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.events.GameEvent.EventType; -import mage.game.permanent.Permanent; import mage.target.TargetPermanent; /** @@ -75,12 +67,11 @@ public class AmberPrison extends CardImpl { this.addAbility(new SkipUntapOptionalAbility()); // {4}, {tap}: Tap target artifact, creature, or land. That permanent doesn't untap during its controller's untap step for as long as Amber Prison remains tapped. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new AmberPrisonTapTargetEffect(), new GenericManaCost(4)); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TapTargetEffect(true), new GenericManaCost(4)); ability.addCost(new TapSourceCost()); ability.addTarget(new TargetPermanent(filter)); + ability.addEffect(new DontUntapAsLongAsSourceTappedEffect()); this.addAbility(ability); - this.addAbility(new AmberPrisonUntapTriggeredAbility()); - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new AmberPrisonRestrictionEffect())); } public AmberPrison(final AmberPrison card) { @@ -92,124 +83,3 @@ public class AmberPrison extends CardImpl { return new AmberPrison(this); } } - -class AmberPrisonTapTargetEffect extends OneShotEffect { - - public AmberPrisonTapTargetEffect() { - super(Outcome.Tap); - this.staticText = "Tap target artifact, creature, or land. That permanent doesn't untap during its controller's untap step for as long as {source} remains tapped."; - } - - public AmberPrisonTapTargetEffect(final AmberPrisonTapTargetEffect effect) { - super(effect); - } - - @Override - public AmberPrisonTapTargetEffect copy() { - return new AmberPrisonTapTargetEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent sourcePermanent = game.getPermanent(source.getSourceId()); - for (UUID target : targetPointer.getTargets(game, source)) { - Permanent permanent = game.getPermanent(target); - if (permanent != null) { - if (sourcePermanent != null) { - sourcePermanent.addConnectedCard("AmberPrison", permanent.getId()); - } - permanent.tap(game); - } - } - return true; - } - -} - -class AmberPrisonRestrictionEffect extends RestrictionEffect { - - public AmberPrisonRestrictionEffect() { - super(Duration.WhileOnBattlefield); - } - - public AmberPrisonRestrictionEffect(final AmberPrisonRestrictionEffect effect) { - super(effect); - } - - @Override - public AmberPrisonRestrictionEffect copy() { - return new AmberPrisonRestrictionEffect(this); - } - - @Override - public boolean applies(Permanent permanent, Ability source, Game game) { - Permanent sourcePermanent = game.getPermanent(source.getSourceId()); - if (sourcePermanent != null && sourcePermanent.isTapped()) { - if (sourcePermanent.getConnectedCards("AmberPrison") != null) { - return sourcePermanent.getConnectedCards("AmberPrison").contains(permanent.getId()); - } - } - return false; - } - - @Override - public boolean canBeUntapped(Permanent permanent, Ability source, Game game) { - return false; - } - -} - -class AmberPrisonUntapTriggeredAbility extends TriggeredAbilityImpl { - - public AmberPrisonUntapTriggeredAbility() { - super(Zone.BATTLEFIELD, new AmberPrisonReleaseOnUntapEffect(), false); - this.usesStack = false; - this.ruleVisible = false; - } - - public AmberPrisonUntapTriggeredAbility(final AmberPrisonUntapTriggeredAbility ability) { - super(ability); - } - - @Override - public AmberPrisonUntapTriggeredAbility copy() { - return new AmberPrisonUntapTriggeredAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == EventType.UNTAP; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - return event.getTargetId().equals(this.getSourceId()); - } -} - -class AmberPrisonReleaseOnUntapEffect extends OneShotEffect { - - public AmberPrisonReleaseOnUntapEffect() { - super(Outcome.Detriment); - } - - public AmberPrisonReleaseOnUntapEffect(final AmberPrisonReleaseOnUntapEffect effect) { - super(effect); - } - - @Override - public AmberPrisonReleaseOnUntapEffect copy() { - return new AmberPrisonReleaseOnUntapEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent sourcePermanent = game.getPermanent(source.getSourceId()); - if (sourcePermanent != null) { - sourcePermanent.clearConnectedCards("AmberPrison"); - return true; - } - return false; - } - -} diff --git a/Mage.Sets/src/mage/sets/scarsofmirrodin/RustTick.java b/Mage.Sets/src/mage/sets/scarsofmirrodin/RustTick.java index db24b40406..01a7294134 100644 --- a/Mage.Sets/src/mage/sets/scarsofmirrodin/RustTick.java +++ b/Mage.Sets/src/mage/sets/scarsofmirrodin/RustTick.java @@ -30,22 +30,17 @@ package mage.sets.scarsofmirrodin; import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.Mode; import mage.abilities.common.SimpleActivatedAbility; -import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SkipUntapOptionalAbility; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.effects.RestrictionEffect; import mage.abilities.effects.common.TapTargetEffect; import mage.cards.CardImpl; import mage.constants.CardType; -import mage.constants.Duration; import mage.constants.Rarity; import mage.constants.Zone; -import mage.game.Game; -import mage.game.permanent.Permanent; import mage.target.common.TargetArtifactPermanent; +import mage.abilities.effects.common.DontUntapAsLongAsSourceTappedEffect; /** * @author nantuko @@ -64,12 +59,11 @@ public class RustTick extends CardImpl { this.addAbility(new SkipUntapOptionalAbility()); // {1}, {tap}: Tap target artifact. It doesn't untap during its controller's untap step for as long as Rust Tick remains tapped. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new RustTickTapTargetEffect(), new GenericManaCost(1)); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TapTargetEffect(true), new GenericManaCost(1)); ability.addCost(new TapSourceCost()); ability.addTarget(new TargetArtifactPermanent()); + ability.addEffect(new DontUntapAsLongAsSourceTappedEffect()); this.addAbility(ability); - - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new RustTickRestrictionEffect())); } public RustTick(final RustTick card) { @@ -81,79 +75,3 @@ public class RustTick extends CardImpl { return new RustTick(this); } } - -class RustTickTapTargetEffect extends TapTargetEffect { - - public RustTickTapTargetEffect() { - super(); - staticText = "Tap target artifact. It doesn't untap during its controller's untap step for as long as Rust Tick remains tapped"; - } - - public RustTickTapTargetEffect(final RustTickTapTargetEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent rustTick = game.getPermanent(source.getSourceId()); - if (rustTick != null) { - rustTick.clearConnectedCards("RustTick"); - } - for (UUID target : targetPointer.getTargets(game, source)) { - Permanent permanent = game.getPermanent(target); - if (permanent != null) { - rustTick.addConnectedCard("RustTick", permanent.getId()); - permanent.tap(game); - } else { - return false; - } - } - return true; - } - - @Override - public RustTickTapTargetEffect copy() { - return new RustTickTapTargetEffect(this); - } - - @Override - public String getText(Mode mode) { - return staticText; - } -} - -class RustTickRestrictionEffect extends RestrictionEffect { - - public RustTickRestrictionEffect() { - super(Duration.WhileOnBattlefield); - } - - public RustTickRestrictionEffect(final RustTickRestrictionEffect effect) { - super(effect); - } - - @Override - public boolean applies(Permanent permanent, Ability source, Game game) { - Permanent rustTick = game.getPermanent(source.getSourceId()); - if (rustTick != null && rustTick.isTapped()) { - if (rustTick.getConnectedCards("RustTick").size() > 0) { - UUID target = rustTick.getConnectedCards("RustTick").get(0); - if (target != null && target.equals(permanent.getId())) { - return true; - } - } - } - return false; - } - - @Override - public boolean canBeUntapped(Permanent permanent, Ability source, Game game) { - return false; - } - - @Override - public RustTickRestrictionEffect copy() { - return new RustTickRestrictionEffect(this); - } - -} diff --git a/Mage.Sets/src/mage/sets/tempest/ThalakosDreamsower.java b/Mage.Sets/src/mage/sets/tempest/ThalakosDreamsower.java new file mode 100644 index 0000000000..d03c8eb1d4 --- /dev/null +++ b/Mage.Sets/src/mage/sets/tempest/ThalakosDreamsower.java @@ -0,0 +1,76 @@ +/* + * 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.tempest; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.DealsDamageToOpponentTriggeredAbility; +import mage.abilities.common.SkipUntapOptionalAbility; +import mage.abilities.effects.common.DontUntapAsLongAsSourceTappedEffect; +import mage.abilities.effects.common.TapTargetEffect; +import mage.abilities.keyword.ShadowAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LoneFox + */ +public class ThalakosDreamsower extends CardImpl { + + public ThalakosDreamsower(UUID ownerId) { + super(ownerId, 92, "Thalakos Dreamsower", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{2}{U}"); + this.expansionSetCode = "TMP"; + this.subtype.add("Thalakos"); + this.subtype.add("Wizard"); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Shadow + this.addAbility(ShadowAbility.getInstance()); + // You may choose not to untap Thalakos Dreamsower during your untap step. + this.addAbility(new SkipUntapOptionalAbility()); + // Whenever Thalakos Dreamsower deals damage to an opponent, tap target creature. That creature doesn't untap during its controller's untap step for as long as Thalakos Dreamsower remains tapped. + Ability ability = new DealsDamageToOpponentTriggeredAbility(new TapTargetEffect(true), false); + ability.addTarget(new TargetCreaturePermanent()); + ability.addEffect(new DontUntapAsLongAsSourceTappedEffect()); + this.addAbility(ability); + } + + public ThalakosDreamsower(final ThalakosDreamsower card) { + super(card); + } + + @Override + public ThalakosDreamsower copy() { + return new ThalakosDreamsower(this); + } +} diff --git a/Mage/src/mage/abilities/effects/common/DontUntapAsLongAsSourceTappedEffect.java b/Mage/src/mage/abilities/effects/common/DontUntapAsLongAsSourceTappedEffect.java new file mode 100644 index 0000000000..b6ee8a4061 --- /dev/null +++ b/Mage/src/mage/abilities/effects/common/DontUntapAsLongAsSourceTappedEffect.java @@ -0,0 +1,78 @@ +/* + * 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.abilities.effects.common; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.RestrictionEffect; +import mage.constants.Duration; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * + * @author LoneFox + */ + +public class DontUntapAsLongAsSourceTappedEffect extends RestrictionEffect { + + public DontUntapAsLongAsSourceTappedEffect() { + super(Duration.WhileOnBattlefield); + staticText = "It doesn't untap during its controller's untap step for as long as {source} remains tapped."; + } + + public DontUntapAsLongAsSourceTappedEffect(final DontUntapAsLongAsSourceTappedEffect effect) { + super(effect); + } + + @Override + public boolean applies(Permanent permanent, Ability source, Game game) { + Permanent sourcePermanent = game.getPermanent(source.getSourceId()); + if(sourcePermanent != null && sourcePermanent.isTapped()) { + String name = sourcePermanent.getName(); + if(sourcePermanent.getConnectedCards(name).size() > 0) { + UUID target = sourcePermanent.getConnectedCards(name).get(0); + if(target != null && target.equals(permanent.getId())) { + return true; + } + } + } + return false; + } + + @Override + public boolean canBeUntapped(Permanent permanent, Ability source, Game game) { + return false; + } + + @Override + public DontUntapAsLongAsSourceTappedEffect copy() { + return new DontUntapAsLongAsSourceTappedEffect(this); + } +} diff --git a/Mage/src/mage/abilities/effects/common/TapTargetEffect.java b/Mage/src/mage/abilities/effects/common/TapTargetEffect.java index e8fa976f4b..964f24bf53 100644 --- a/Mage/src/mage/abilities/effects/common/TapTargetEffect.java +++ b/Mage/src/mage/abilities/effects/common/TapTargetEffect.java @@ -28,15 +28,14 @@ package mage.abilities.effects.common; -import mage.constants.Outcome; +import java.util.UUID; import mage.abilities.Ability; import mage.abilities.Mode; import mage.abilities.effects.OneShotEffect; +import mage.constants.Outcome; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.Target; - -import java.util.UUID; import mage.util.CardUtil; /** @@ -44,17 +43,31 @@ import mage.util.CardUtil; */ public class TapTargetEffect extends OneShotEffect { + private final boolean connectSource; + public TapTargetEffect() { - super(Outcome.Tap); + this(null, false); + } + + public TapTargetEffect(boolean connectSource) { + this(null, connectSource); } public TapTargetEffect(String text) { - this(); - this.staticText = text; + this(text, false); + } + + public TapTargetEffect(String text, boolean connectSource) { + super(Outcome.Tap); + this.connectSource = connectSource; + if(text != null) { + this.staticText = text; + } } public TapTargetEffect(final TapTargetEffect effect) { super(effect); + this.connectSource = effect.connectSource; } @Override @@ -68,6 +81,12 @@ public class TapTargetEffect extends OneShotEffect { Permanent permanent = game.getPermanent(target); if (permanent != null) { permanent.tap(game); + if(connectSource) { + Permanent sourcePermanent = game.getPermanent(source.getSourceId()); + if(sourcePermanent != null) { + sourcePermanent.addConnectedCard(sourcePermanent.getName(), permanent.getId()); + } + } } } return true; From d9e1a72ad1d49c4c68c4a25988b935a13bfeccbe Mon Sep 17 00:00:00 2001 From: LoneFox Date: Tue, 29 Sep 2015 13:40:34 +0300 Subject: [PATCH 12/16] Implement cards: Mana Leech, Mole Worms, Phyrexian Gremlins, Sand Squid, and Whip Vine --- .../src/mage/sets/alliances/WhipVine1.java | 88 +++++++++++++++++++ .../src/mage/sets/alliances/WhipVine2.java | 51 +++++++++++ .../sets/antiquities/PhyrexianGremlins.java | 74 ++++++++++++++++ .../src/mage/sets/fifthedition/MoleWorms.java | 74 ++++++++++++++++ Mage.Sets/src/mage/sets/iceage/MoleWorms.java | 52 +++++++++++ .../mage/sets/mercadianmasques/SandSquid.java | 78 ++++++++++++++++ .../src/mage/sets/urzassaga/ManaLeech.java | 74 ++++++++++++++++ 7 files changed, 491 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/alliances/WhipVine1.java create mode 100644 Mage.Sets/src/mage/sets/alliances/WhipVine2.java create mode 100644 Mage.Sets/src/mage/sets/antiquities/PhyrexianGremlins.java create mode 100644 Mage.Sets/src/mage/sets/fifthedition/MoleWorms.java create mode 100644 Mage.Sets/src/mage/sets/iceage/MoleWorms.java create mode 100644 Mage.Sets/src/mage/sets/mercadianmasques/SandSquid.java create mode 100644 Mage.Sets/src/mage/sets/urzassaga/ManaLeech.java diff --git a/Mage.Sets/src/mage/sets/alliances/WhipVine1.java b/Mage.Sets/src/mage/sets/alliances/WhipVine1.java new file mode 100644 index 0000000000..f61edc0825 --- /dev/null +++ b/Mage.Sets/src/mage/sets/alliances/WhipVine1.java @@ -0,0 +1,88 @@ +/* + * 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.alliances; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SkipUntapOptionalAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.common.DontUntapAsLongAsSourceTappedEffect; +import mage.abilities.effects.common.TapTargetEffect; +import mage.abilities.keyword.DefenderAbility; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.ReachAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.filter.predicate.permanent.BlockedByIdPredicate; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LoneFox + */ +public class WhipVine1 extends CardImpl { + + public WhipVine1(UUID ownerId) { + super(ownerId, 89, "Whip Vine", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{2}{G}"); + this.expansionSetCode = "ALL"; + this.subtype.add("Plant"); + this.subtype.add("Wall"); + this.power = new MageInt(1); + this.toughness = new MageInt(4); + + // Defender + this.addAbility(DefenderAbility.getInstance()); + // Reach + this.addAbility(ReachAbility.getInstance()); + // You may choose not to untap Whip Vine during your untap step. + this.addAbility(new SkipUntapOptionalAbility()); + // {tap}: Tap target creature with flying blocked by Whip Vine. That creature doesn't untap during its controller's untap step for as long as Whip Vine remains tapped. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TapTargetEffect(true), new TapSourceCost()); + FilterCreaturePermanent filter = new FilterCreaturePermanent("creature with flying blocked by {this}"); + filter.add(new AbilityPredicate(FlyingAbility.class)); + filter.add(new BlockedByIdPredicate(this.getId())); + ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addEffect(new DontUntapAsLongAsSourceTappedEffect()); + this.addAbility(ability); + } + + public WhipVine1(final WhipVine1 card) { + super(card); + } + + @Override + public WhipVine1 copy() { + return new WhipVine1(this); + } +} diff --git a/Mage.Sets/src/mage/sets/alliances/WhipVine2.java b/Mage.Sets/src/mage/sets/alliances/WhipVine2.java new file mode 100644 index 0000000000..33fab71847 --- /dev/null +++ b/Mage.Sets/src/mage/sets/alliances/WhipVine2.java @@ -0,0 +1,51 @@ +/* + * 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.alliances; + +import java.util.UUID; + +/** + * + * @author LoneFox + */ +public class WhipVine2 extends WhipVine1 { + + public WhipVine2(UUID ownerId) { + super(ownerId); + this.cardNumber = 90; + } + + public WhipVine2(final WhipVine2 card) { + super(card); + } + + @Override + public WhipVine2 copy() { + return new WhipVine2(this); + } +} diff --git a/Mage.Sets/src/mage/sets/antiquities/PhyrexianGremlins.java b/Mage.Sets/src/mage/sets/antiquities/PhyrexianGremlins.java new file mode 100644 index 0000000000..5cd0d3025e --- /dev/null +++ b/Mage.Sets/src/mage/sets/antiquities/PhyrexianGremlins.java @@ -0,0 +1,74 @@ +/* + * 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.antiquities; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SkipUntapOptionalAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.common.DontUntapAsLongAsSourceTappedEffect; +import mage.abilities.effects.common.TapTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.target.common.TargetArtifactPermanent; + +/** + * + * @author LoneFox + */ +public class PhyrexianGremlins extends CardImpl { + + public PhyrexianGremlins(UUID ownerId) { + super(ownerId, 48, "Phyrexian Gremlins", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{2}{B}"); + this.expansionSetCode = "ATQ"; + this.subtype.add("Gremlin"); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // You may choose not to untap Phyrexian Gremlins during your untap step. + this.addAbility(new SkipUntapOptionalAbility()); + // {tap}: Tap target artifact. It doesn't untap during its controller's untap step for as long as Phyrexian Gremlins remains tapped. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TapTargetEffect(true), new TapSourceCost()); + ability.addTarget(new TargetArtifactPermanent()); + ability.addEffect(new DontUntapAsLongAsSourceTappedEffect()); + this.addAbility(ability); + } + + public PhyrexianGremlins(final PhyrexianGremlins card) { + super(card); + } + + @Override + public PhyrexianGremlins copy() { + return new PhyrexianGremlins(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fifthedition/MoleWorms.java b/Mage.Sets/src/mage/sets/fifthedition/MoleWorms.java new file mode 100644 index 0000000000..406be0a63c --- /dev/null +++ b/Mage.Sets/src/mage/sets/fifthedition/MoleWorms.java @@ -0,0 +1,74 @@ +/* + * 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.fifthedition; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SkipUntapOptionalAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.common.DontUntapAsLongAsSourceTappedEffect; +import mage.abilities.effects.common.TapTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.target.common.TargetLandPermanent; + +/** + * + * @author LoneFox + */ +public class MoleWorms extends CardImpl { + + public MoleWorms(UUID ownerId) { + super(ownerId, 41, "Mole Worms", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{2}{B}"); + this.expansionSetCode = "5ED"; + this.subtype.add("Worm"); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // You may choose not to untap Mole Worms during your untap step. + this.addAbility(new SkipUntapOptionalAbility()); + // {tap}: Tap target land. It doesn't untap during its controller's untap step for as long as Mole Worms remains tapped. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TapTargetEffect(true), new TapSourceCost()); + ability.addTarget(new TargetLandPermanent()); + ability.addEffect(new DontUntapAsLongAsSourceTappedEffect()); + this.addAbility(ability); + } + + public MoleWorms(final MoleWorms card) { + super(card); + } + + @Override + public MoleWorms copy() { + return new MoleWorms(this); + } +} diff --git a/Mage.Sets/src/mage/sets/iceage/MoleWorms.java b/Mage.Sets/src/mage/sets/iceage/MoleWorms.java new file mode 100644 index 0000000000..b7f0081bd3 --- /dev/null +++ b/Mage.Sets/src/mage/sets/iceage/MoleWorms.java @@ -0,0 +1,52 @@ +/* + * 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.iceage; + +import java.util.UUID; + +/** + * + * @author LoneFox + */ +public class MoleWorms extends mage.sets.fifthedition.MoleWorms { + + public MoleWorms(UUID ownerId) { + super(ownerId); + this.cardNumber = 40; + this.expansionSetCode = "ICE"; + } + + public MoleWorms(final MoleWorms card) { + super(card); + } + + @Override + public MoleWorms copy() { + return new MoleWorms(this); + } +} diff --git a/Mage.Sets/src/mage/sets/mercadianmasques/SandSquid.java b/Mage.Sets/src/mage/sets/mercadianmasques/SandSquid.java new file mode 100644 index 0000000000..4494462caa --- /dev/null +++ b/Mage.Sets/src/mage/sets/mercadianmasques/SandSquid.java @@ -0,0 +1,78 @@ +/* + * 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.mercadianmasques; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SkipUntapOptionalAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.common.DontUntapAsLongAsSourceTappedEffect; +import mage.abilities.effects.common.TapTargetEffect; +import mage.abilities.keyword.IslandwalkAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LoneFox + */ +public class SandSquid extends CardImpl { + + public SandSquid(UUID ownerId) { + super(ownerId, 96, "Sand Squid", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{3}{U}"); + this.expansionSetCode = "MMQ"; + this.subtype.add("Squid"); + this.subtype.add("Beast"); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Islandwalk + this.addAbility(new IslandwalkAbility()); + // You may choose not to untap Sand Squid during your untap step. + this.addAbility(new SkipUntapOptionalAbility()); + // {tap}: Tap target creature. That creature doesn't untap during its controller's untap step for as long as Sand Squid remains tapped. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TapTargetEffect(true), new TapSourceCost()); + ability.addTarget(new TargetCreaturePermanent()); + ability.addEffect(new DontUntapAsLongAsSourceTappedEffect()); + this.addAbility(ability); + } + + public SandSquid(final SandSquid card) { + super(card); + } + + @Override + public SandSquid copy() { + return new SandSquid(this); + } +} diff --git a/Mage.Sets/src/mage/sets/urzassaga/ManaLeech.java b/Mage.Sets/src/mage/sets/urzassaga/ManaLeech.java new file mode 100644 index 0000000000..4877799957 --- /dev/null +++ b/Mage.Sets/src/mage/sets/urzassaga/ManaLeech.java @@ -0,0 +1,74 @@ +/* + * 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.urzassaga; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SkipUntapOptionalAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.common.DontUntapAsLongAsSourceTappedEffect; +import mage.abilities.effects.common.TapTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.target.common.TargetLandPermanent; + +/** + * + * @author LoneFox + */ +public class ManaLeech extends CardImpl { + + public ManaLeech(UUID ownerId) { + super(ownerId, 141, "Mana Leech", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{2}{B}"); + this.expansionSetCode = "USG"; + this.subtype.add("Leech"); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // You may choose not to untap Mana Leech during your untap step. + this.addAbility(new SkipUntapOptionalAbility()); + // {tap}: Tap target land. It doesn't untap during its controller's untap step for as long as Mana Leech remains tapped. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TapTargetEffect(true), new TapSourceCost()); + ability.addTarget(new TargetLandPermanent()); + ability.addEffect(new DontUntapAsLongAsSourceTappedEffect()); + this.addAbility(ability); + } + + public ManaLeech(final ManaLeech card) { + super(card); + } + + @Override + public ManaLeech copy() { + return new ManaLeech(this); + } +} From 705bdabafbfb47de85f9d24a4d1ca065bdb93d86 Mon Sep 17 00:00:00 2001 From: LoneFox Date: Tue, 29 Sep 2015 15:11:01 +0300 Subject: [PATCH 13/16] Much simpler way to implement DontUntapAsLongAsSourceTappedEffect. This also works correctly when the source permanent untaps and then taps again. --- .../DontUntapAsLongAsSourceTappedEffect.java | 30 +++++++------------ 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/Mage/src/mage/abilities/effects/common/DontUntapAsLongAsSourceTappedEffect.java b/Mage/src/mage/abilities/effects/common/DontUntapAsLongAsSourceTappedEffect.java index b6ee8a4061..f84dc06cee 100644 --- a/Mage/src/mage/abilities/effects/common/DontUntapAsLongAsSourceTappedEffect.java +++ b/Mage/src/mage/abilities/effects/common/DontUntapAsLongAsSourceTappedEffect.java @@ -30,20 +30,22 @@ package mage.abilities.effects.common; import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.effects.RestrictionEffect; +import mage.abilities.condition.common.SourceTappedCondition; +import mage.abilities.decorator.ConditionalContinuousRuleModifyingEffect; +import mage.abilities.effects.common.DontUntapInControllersUntapStepTargetEffect; import mage.constants.Duration; import mage.game.Game; -import mage.game.permanent.Permanent; +import mage.game.events.GameEvent; /** * * @author LoneFox */ -public class DontUntapAsLongAsSourceTappedEffect extends RestrictionEffect { +public class DontUntapAsLongAsSourceTappedEffect extends ConditionalContinuousRuleModifyingEffect { public DontUntapAsLongAsSourceTappedEffect() { - super(Duration.WhileOnBattlefield); + super(new DontUntapInControllersUntapStepTargetEffect(Duration.Custom), SourceTappedCondition.getInstance()); staticText = "It doesn't untap during its controller's untap step for as long as {source} remains tapped."; } @@ -52,23 +54,11 @@ public class DontUntapAsLongAsSourceTappedEffect extends RestrictionEffect { } @Override - public boolean applies(Permanent permanent, Ability source, Game game) { - Permanent sourcePermanent = game.getPermanent(source.getSourceId()); - if(sourcePermanent != null && sourcePermanent.isTapped()) { - String name = sourcePermanent.getName(); - if(sourcePermanent.getConnectedCards(name).size() > 0) { - UUID target = sourcePermanent.getConnectedCards(name).get(0); - if(target != null && target.equals(permanent.getId())) { - return true; - } - } + public boolean applies(GameEvent event, Ability source, Game game) { + if(event.getType() == GameEvent.EventType.UNTAP && event.getTargetId().equals(source.getSourceId())) { + effect.discard(); } - return false; - } - - @Override - public boolean canBeUntapped(Permanent permanent, Ability source, Game game) { - return false; + return super.applies(event, source, game); } @Override From ab0e4b0ddcec970aec90a302fe288e229cf7c458 Mon Sep 17 00:00:00 2001 From: LoneFox Date: Tue, 29 Sep 2015 15:25:52 +0300 Subject: [PATCH 14/16] Revert connectSource changes from TapTargetEffect. Not needed anymore. --- .../src/mage/sets/alliances/WhipVine1.java | 2 +- .../sets/antiquities/PhyrexianGremlins.java | 2 +- .../src/mage/sets/fifthedition/MoleWorms.java | 2 +- .../journeyintonyx/DesertersQuarters.java | 2 +- .../mage/sets/mercadianmasques/SandSquid.java | 2 +- .../src/mage/sets/mirage/AmberPrison.java | 2 +- .../mage/sets/scarsofmirrodin/RustTick.java | 2 +- .../mage/sets/tempest/ThalakosDreamsower.java | 2 +- .../src/mage/sets/urzassaga/ManaLeech.java | 2 +- .../effects/common/TapTargetEffect.java | 20 +------------------ 10 files changed, 10 insertions(+), 28 deletions(-) diff --git a/Mage.Sets/src/mage/sets/alliances/WhipVine1.java b/Mage.Sets/src/mage/sets/alliances/WhipVine1.java index f61edc0825..f10a6da77b 100644 --- a/Mage.Sets/src/mage/sets/alliances/WhipVine1.java +++ b/Mage.Sets/src/mage/sets/alliances/WhipVine1.java @@ -68,7 +68,7 @@ public class WhipVine1 extends CardImpl { // You may choose not to untap Whip Vine during your untap step. this.addAbility(new SkipUntapOptionalAbility()); // {tap}: Tap target creature with flying blocked by Whip Vine. That creature doesn't untap during its controller's untap step for as long as Whip Vine remains tapped. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TapTargetEffect(true), new TapSourceCost()); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TapTargetEffect(), new TapSourceCost()); FilterCreaturePermanent filter = new FilterCreaturePermanent("creature with flying blocked by {this}"); filter.add(new AbilityPredicate(FlyingAbility.class)); filter.add(new BlockedByIdPredicate(this.getId())); diff --git a/Mage.Sets/src/mage/sets/antiquities/PhyrexianGremlins.java b/Mage.Sets/src/mage/sets/antiquities/PhyrexianGremlins.java index 5cd0d3025e..884198052d 100644 --- a/Mage.Sets/src/mage/sets/antiquities/PhyrexianGremlins.java +++ b/Mage.Sets/src/mage/sets/antiquities/PhyrexianGremlins.java @@ -57,7 +57,7 @@ public class PhyrexianGremlins extends CardImpl { // You may choose not to untap Phyrexian Gremlins during your untap step. this.addAbility(new SkipUntapOptionalAbility()); // {tap}: Tap target artifact. It doesn't untap during its controller's untap step for as long as Phyrexian Gremlins remains tapped. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TapTargetEffect(true), new TapSourceCost()); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TapTargetEffect(), new TapSourceCost()); ability.addTarget(new TargetArtifactPermanent()); ability.addEffect(new DontUntapAsLongAsSourceTappedEffect()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/sets/fifthedition/MoleWorms.java b/Mage.Sets/src/mage/sets/fifthedition/MoleWorms.java index 406be0a63c..eefb06798f 100644 --- a/Mage.Sets/src/mage/sets/fifthedition/MoleWorms.java +++ b/Mage.Sets/src/mage/sets/fifthedition/MoleWorms.java @@ -57,7 +57,7 @@ public class MoleWorms extends CardImpl { // You may choose not to untap Mole Worms during your untap step. this.addAbility(new SkipUntapOptionalAbility()); // {tap}: Tap target land. It doesn't untap during its controller's untap step for as long as Mole Worms remains tapped. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TapTargetEffect(true), new TapSourceCost()); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TapTargetEffect(), new TapSourceCost()); ability.addTarget(new TargetLandPermanent()); ability.addEffect(new DontUntapAsLongAsSourceTappedEffect()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/sets/journeyintonyx/DesertersQuarters.java b/Mage.Sets/src/mage/sets/journeyintonyx/DesertersQuarters.java index 6604ae9340..37de64705d 100644 --- a/Mage.Sets/src/mage/sets/journeyintonyx/DesertersQuarters.java +++ b/Mage.Sets/src/mage/sets/journeyintonyx/DesertersQuarters.java @@ -55,7 +55,7 @@ public class DesertersQuarters extends CardImpl { this.addAbility(new SkipUntapOptionalAbility()); // {6}, T: Tap target creature. It doesn't untap during its controller's untap step for as long as Deserter's Quarters remains tapped. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TapTargetEffect(true), new GenericManaCost(6)); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TapTargetEffect(), new GenericManaCost(6)); ability.addCost(new TapSourceCost()); ability.addTarget(new TargetCreaturePermanent()); ability.addEffect(new DontUntapAsLongAsSourceTappedEffect()); diff --git a/Mage.Sets/src/mage/sets/mercadianmasques/SandSquid.java b/Mage.Sets/src/mage/sets/mercadianmasques/SandSquid.java index 4494462caa..dfe44fc04c 100644 --- a/Mage.Sets/src/mage/sets/mercadianmasques/SandSquid.java +++ b/Mage.Sets/src/mage/sets/mercadianmasques/SandSquid.java @@ -61,7 +61,7 @@ public class SandSquid extends CardImpl { // You may choose not to untap Sand Squid during your untap step. this.addAbility(new SkipUntapOptionalAbility()); // {tap}: Tap target creature. That creature doesn't untap during its controller's untap step for as long as Sand Squid remains tapped. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TapTargetEffect(true), new TapSourceCost()); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TapTargetEffect(), new TapSourceCost()); ability.addTarget(new TargetCreaturePermanent()); ability.addEffect(new DontUntapAsLongAsSourceTappedEffect()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/sets/mirage/AmberPrison.java b/Mage.Sets/src/mage/sets/mirage/AmberPrison.java index 4e1de790d6..ad18768cb6 100644 --- a/Mage.Sets/src/mage/sets/mirage/AmberPrison.java +++ b/Mage.Sets/src/mage/sets/mirage/AmberPrison.java @@ -67,7 +67,7 @@ public class AmberPrison extends CardImpl { this.addAbility(new SkipUntapOptionalAbility()); // {4}, {tap}: Tap target artifact, creature, or land. That permanent doesn't untap during its controller's untap step for as long as Amber Prison remains tapped. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TapTargetEffect(true), new GenericManaCost(4)); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TapTargetEffect(), new GenericManaCost(4)); ability.addCost(new TapSourceCost()); ability.addTarget(new TargetPermanent(filter)); ability.addEffect(new DontUntapAsLongAsSourceTappedEffect()); diff --git a/Mage.Sets/src/mage/sets/scarsofmirrodin/RustTick.java b/Mage.Sets/src/mage/sets/scarsofmirrodin/RustTick.java index 01a7294134..213dc1eb43 100644 --- a/Mage.Sets/src/mage/sets/scarsofmirrodin/RustTick.java +++ b/Mage.Sets/src/mage/sets/scarsofmirrodin/RustTick.java @@ -59,7 +59,7 @@ public class RustTick extends CardImpl { this.addAbility(new SkipUntapOptionalAbility()); // {1}, {tap}: Tap target artifact. It doesn't untap during its controller's untap step for as long as Rust Tick remains tapped. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TapTargetEffect(true), new GenericManaCost(1)); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TapTargetEffect(), new GenericManaCost(1)); ability.addCost(new TapSourceCost()); ability.addTarget(new TargetArtifactPermanent()); ability.addEffect(new DontUntapAsLongAsSourceTappedEffect()); diff --git a/Mage.Sets/src/mage/sets/tempest/ThalakosDreamsower.java b/Mage.Sets/src/mage/sets/tempest/ThalakosDreamsower.java index d03c8eb1d4..5364030608 100644 --- a/Mage.Sets/src/mage/sets/tempest/ThalakosDreamsower.java +++ b/Mage.Sets/src/mage/sets/tempest/ThalakosDreamsower.java @@ -59,7 +59,7 @@ public class ThalakosDreamsower extends CardImpl { // You may choose not to untap Thalakos Dreamsower during your untap step. this.addAbility(new SkipUntapOptionalAbility()); // Whenever Thalakos Dreamsower deals damage to an opponent, tap target creature. That creature doesn't untap during its controller's untap step for as long as Thalakos Dreamsower remains tapped. - Ability ability = new DealsDamageToOpponentTriggeredAbility(new TapTargetEffect(true), false); + Ability ability = new DealsDamageToOpponentTriggeredAbility(new TapTargetEffect(), false); ability.addTarget(new TargetCreaturePermanent()); ability.addEffect(new DontUntapAsLongAsSourceTappedEffect()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/sets/urzassaga/ManaLeech.java b/Mage.Sets/src/mage/sets/urzassaga/ManaLeech.java index 4877799957..9879b1c982 100644 --- a/Mage.Sets/src/mage/sets/urzassaga/ManaLeech.java +++ b/Mage.Sets/src/mage/sets/urzassaga/ManaLeech.java @@ -57,7 +57,7 @@ public class ManaLeech extends CardImpl { // You may choose not to untap Mana Leech during your untap step. this.addAbility(new SkipUntapOptionalAbility()); // {tap}: Tap target land. It doesn't untap during its controller's untap step for as long as Mana Leech remains tapped. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TapTargetEffect(true), new TapSourceCost()); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TapTargetEffect(), new TapSourceCost()); ability.addTarget(new TargetLandPermanent()); ability.addEffect(new DontUntapAsLongAsSourceTappedEffect()); this.addAbility(ability); diff --git a/Mage/src/mage/abilities/effects/common/TapTargetEffect.java b/Mage/src/mage/abilities/effects/common/TapTargetEffect.java index 964f24bf53..efc2b9321d 100644 --- a/Mage/src/mage/abilities/effects/common/TapTargetEffect.java +++ b/Mage/src/mage/abilities/effects/common/TapTargetEffect.java @@ -43,23 +43,12 @@ import mage.util.CardUtil; */ public class TapTargetEffect extends OneShotEffect { - private final boolean connectSource; - public TapTargetEffect() { - this(null, false); - } - - public TapTargetEffect(boolean connectSource) { - this(null, connectSource); + super(Outcome.Tap); } public TapTargetEffect(String text) { - this(text, false); - } - - public TapTargetEffect(String text, boolean connectSource) { super(Outcome.Tap); - this.connectSource = connectSource; if(text != null) { this.staticText = text; } @@ -67,7 +56,6 @@ public class TapTargetEffect extends OneShotEffect { public TapTargetEffect(final TapTargetEffect effect) { super(effect); - this.connectSource = effect.connectSource; } @Override @@ -81,12 +69,6 @@ public class TapTargetEffect extends OneShotEffect { Permanent permanent = game.getPermanent(target); if (permanent != null) { permanent.tap(game); - if(connectSource) { - Permanent sourcePermanent = game.getPermanent(source.getSourceId()); - if(sourcePermanent != null) { - sourcePermanent.addConnectedCard(sourcePermanent.getName(), permanent.getId()); - } - } } } return true; From e2453abbb5f991ba747211c0b383d49c9a355d14 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Tue, 29 Sep 2015 17:26:29 +0200 Subject: [PATCH 15/16] * Fixed a bug that some options in preferences were handled with the wrong state as long as never set manually. --- .../java/mage/client/dialog/PreferencesDialog.java | 1 + Mage.Server/src/main/java/mage/server/Session.java | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java b/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java index c8f314e4a8..e84416bcdf 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java @@ -2565,6 +2565,7 @@ public class PreferencesDialog extends javax.swing.JDialog { private static void load(Preferences prefs, JCheckBox checkBox, String propName, String yesValue, String defaultValue) { String prop = prefs.get(propName, defaultValue); checkBox.setSelected(prop.equals(yesValue)); + updateCache(propName, prop); } private static void load(Preferences prefs, JTextField field, String propName, String defaultValue) { diff --git a/Mage.Server/src/main/java/mage/server/Session.java b/Mage.Server/src/main/java/mage/server/Session.java index 16b1da7e51..9a03b6e0e0 100644 --- a/Mage.Server/src/main/java/mage/server/Session.java +++ b/Mage.Server/src/main/java/mage/server/Session.java @@ -92,15 +92,15 @@ public class Session { return "User name Admin already in use"; } if (userName.length() > ConfigSettings.getInstance().getMaxUserNameLength()) { - return new StringBuilder("User name may not be longer than ").append(ConfigSettings.getInstance().getMaxUserNameLength()).append(" characters").toString(); + return "User name may not be longer than " + ConfigSettings.getInstance().getMaxUserNameLength() + " characters"; } if (userName.length() < ConfigSettings.getInstance().getMinUserNameLength()) { - return new StringBuilder("User name may not be shorter than ").append(ConfigSettings.getInstance().getMinUserNameLength()).append(" characters").toString(); + return "User name may not be shorter than " + ConfigSettings.getInstance().getMinUserNameLength() + " characters"; } Pattern p = Pattern.compile(ConfigSettings.getInstance().getUserNamePattern(), Pattern.CASE_INSENSITIVE); Matcher m = p.matcher(userName); if (m.find()) { - return new StringBuilder("User name '").append(userName).append("' includes not allowed characters: use a-z, A-Z and 0-9").toString(); + return "User name '" + userName + "' includes not allowed characters: use a-z, A-Z and 0-9"; } User user = UserManager.getInstance().createUser(userName, host); boolean reconnect = false; @@ -118,11 +118,11 @@ public class Session { SessionManager.getInstance().disconnect(user.getSessionId(), DisconnectReason.ConnectingOtherInstance); } } else { - return new StringBuilder("User name ").append(userName).append(" already in use (or your IP address changed)").toString(); + return "User name " + userName + " already in use (or your IP address changed)"; } } if (!UserManager.getInstance().connectToSession(sessionId, user.getId())) { - return new StringBuilder("Error connecting ").append(userName).toString(); + return "Error connecting " + userName; } this.userId = user.getId(); if (reconnect) { // must be connected to receive the message From 0d755b3c89345e25e3d078eef11c7510e0edde3e Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Tue, 29 Sep 2015 17:37:51 +0200 Subject: [PATCH 16/16] Some minor changes. --- .../magicorigins/JaceTelepathUnbound.java | 4 +- .../src/mage/sets/ravnica/ChordOfCalling.java | 10 ++- .../test/cards/planeswalker/JaceTest.java | 72 +++++++++++++++++++ 3 files changed, 78 insertions(+), 8 deletions(-) create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/planeswalker/JaceTest.java diff --git a/Mage.Sets/src/mage/sets/magicorigins/JaceTelepathUnbound.java b/Mage.Sets/src/mage/sets/magicorigins/JaceTelepathUnbound.java index 32b4489ce8..7fabc19569 100644 --- a/Mage.Sets/src/mage/sets/magicorigins/JaceTelepathUnbound.java +++ b/Mage.Sets/src/mage/sets/magicorigins/JaceTelepathUnbound.java @@ -57,7 +57,7 @@ import mage.game.command.Emblem; import mage.game.events.GameEvent; import mage.game.events.ZoneChangeEvent; import mage.players.Player; -import mage.target.common.TargetCardInGraveyard; +import mage.target.common.TargetCardInYourGraveyard; import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetOpponent; import mage.target.targetpointer.FixedTarget; @@ -88,7 +88,7 @@ public class JaceTelepathUnbound extends CardImpl { // -3: You may cast target instant or sorcery card from your graveyard this turn. If that card would be put into your graveyard this turn, exile it instead. ability = new LoyaltyAbility(new JaceTelepathUnboundEffect(), -3); - ability.addTarget(new TargetCardInGraveyard(new FilterInstantOrSorceryCard())); + ability.addTarget(new TargetCardInYourGraveyard(new FilterInstantOrSorceryCard())); this.addAbility(ability); // -9: You get an emblem with "Whenever you cast a spell, target opponent puts the top five cards of his or her library into his or her graveyard". diff --git a/Mage.Sets/src/mage/sets/ravnica/ChordOfCalling.java b/Mage.Sets/src/mage/sets/ravnica/ChordOfCalling.java index b605b87f8b..4a499e1aa2 100644 --- a/Mage.Sets/src/mage/sets/ravnica/ChordOfCalling.java +++ b/Mage.Sets/src/mage/sets/ravnica/ChordOfCalling.java @@ -28,15 +28,14 @@ package mage.sets.ravnica; import java.util.UUID; - -import mage.constants.CardType; -import mage.constants.Rarity; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; import mage.abilities.keyword.ConvokeAbility; import mage.cards.Card; import mage.cards.CardImpl; +import mage.constants.CardType; import mage.constants.Outcome; +import mage.constants.Rarity; import mage.constants.Zone; import mage.filter.Filter; import mage.filter.FilterCard; @@ -56,8 +55,7 @@ public class ChordOfCalling extends CardImpl { super(ownerId, 156, "Chord of Calling", Rarity.RARE, new CardType[]{CardType.INSTANT}, "{X}{G}{G}{G}"); this.expansionSetCode = "RAV"; - - // Convoke + // Convoke (Your creatures can help cast this spell. Each creature you tap while casting this spell pays for {1} or one mana of that creature's color.) this.addAbility(new ConvokeAbility()); // Search your library for a creature card with converted mana cost X or less and put it onto the battlefield. Then shuffle your library. @@ -97,7 +95,7 @@ class ChordofCallingSearchEffect extends OneShotEffect { filter.add(new CardTypePredicate(CardType.CREATURE)); //Set the mana cost one higher to 'emulate' a less than or equal to comparison. filter.add(new ConvertedManaCostPredicate(Filter.ComparisonType.LessThan, xCost + 1)); - TargetCardInLibrary target = new TargetCardInLibrary(0,1,filter); + TargetCardInLibrary target = new TargetCardInLibrary(0, 1, filter); if (player.searchLibrary(target, game)) { if (target.getTargets().size() > 0) { Card card = player.getLibrary().getCard(target.getFirstTarget(), game); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/planeswalker/JaceTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/planeswalker/JaceTest.java new file mode 100644 index 0000000000..c8e6cd1adf --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/planeswalker/JaceTest.java @@ -0,0 +1,72 @@ +/* + * 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 org.mage.test.cards.planeswalker; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import mage.counters.CounterType; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author LevelX2 + */ +public class JaceTest extends CardTestPlayerBase { + + @Test + public void TelepathUnboundSecondAbility() { + // +1: Up to one target creature gets -2/-0 until your next turn. + // -3: You may cast target instant or sorcery card from your graveyard this turn. If that card would be put into your graveyard this turn, exile it instead. + // -9: You get an emblem with "Whenever you cast a spell, target opponent puts the top five cards of his or her library into his or her graveyard". + addCard(Zone.BATTLEFIELD, playerA, "Jace, Telepath Unbound"); // starts with 7 Loyality counters + + // As an additional cost to cast Magmatic Insight, discard a land card. + // Draw two cards. + addCard(Zone.GRAVEYARD, playerA, "Magmatic Insight");// {R} + addCard(Zone.HAND, playerA, "Plains"); + + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1); + + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "-3: You may cast target instant", "Magmatic Insight"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Magmatic Insight"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertPermanentCount(playerA, "Jace, Telepath Unbound", 1); + assertCounterCount("Jace, Telepath Unbound", CounterType.LOYALTY, 2); // 5 - 3 = 2 + + assertExileCount("Magmatic Insight", 1); + + assertHandCount(playerA, 2); + + } + +}