diff --git a/Mage.Common/src/main/java/mage/utils/MageVersion.java b/Mage.Common/src/main/java/mage/utils/MageVersion.java index 5238bd4f7c..1c572fe2b6 100644 --- a/Mage.Common/src/main/java/mage/utils/MageVersion.java +++ b/Mage.Common/src/main/java/mage/utils/MageVersion.java @@ -41,7 +41,7 @@ public class MageVersion implements Serializable, Comparable { public final static int MAGE_VERSION_MAJOR = 1; public final static int MAGE_VERSION_MINOR = 4; public final static int MAGE_VERSION_PATCH = 26; - public final static String MAGE_VERSION_MINOR_PATCH = "V5"; + public final static String MAGE_VERSION_MINOR_PATCH = "V6"; public final static String MAGE_VERSION_INFO = ""; private final int major; diff --git a/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java b/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java index 69e89b0c08..1e934e1915 100644 --- a/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java +++ b/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java @@ -727,7 +727,10 @@ public class HumanPlayer extends PlayerImpl { // It's end of turn phase if (!skippedAtLeastOnce || (playerId.equals(game.getActivePlayerId()) - && !controllingPlayer.getUserData().getUserSkipPrioritySteps().isStopOnAllEndPhases())) { + && !controllingPlayer + .getUserData() + .getUserSkipPrioritySteps() + .isStopOnAllEndPhases())) { skippedAtLeastOnce = true; if (passWithManaPoolCheck(game)) { return false; @@ -1060,7 +1063,9 @@ public class HumanPlayer extends PlayerImpl { while (!abort) { if (passedAllTurns || passedUntilEndStepBeforeMyTurn - || (!getControllingPlayersUserData(game).getUserSkipPrioritySteps().isStopOnDeclareAttackersDuringSkipAction() + || (!getControllingPlayersUserData(game) + .getUserSkipPrioritySteps() + .isStopOnDeclareAttackersDuringSkipAction() && (passedTurn || passedTurnSkipStack || passedUntilEndOfTurn diff --git a/Mage.Sets/src/mage/cards/a/AcrobaticManeuver.java b/Mage.Sets/src/mage/cards/a/AcrobaticManeuver.java index f5cc01b33f..79d5c8820c 100644 --- a/Mage.Sets/src/mage/cards/a/AcrobaticManeuver.java +++ b/Mage.Sets/src/mage/cards/a/AcrobaticManeuver.java @@ -51,7 +51,7 @@ public class AcrobaticManeuver extends CardImpl { Effect effect = new ExileTargetForSourceEffect(); effect.setApplyEffectsAfter(); this.getSpellAbility().addEffect(effect); - this.getSpellAbility().addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, true)); + this.getSpellAbility().addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect()); // Draw a card. this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1)); diff --git a/Mage.Sets/src/mage/cards/a/AlexiZephyrMage.java b/Mage.Sets/src/mage/cards/a/AlexiZephyrMage.java index bd8ff13e1c..3f55ec6cdb 100644 --- a/Mage.Sets/src/mage/cards/a/AlexiZephyrMage.java +++ b/Mage.Sets/src/mage/cards/a/AlexiZephyrMage.java @@ -42,9 +42,7 @@ import mage.constants.SubType; import mage.constants.SuperType; import mage.constants.Zone; import mage.filter.FilterCard; -import mage.filter.FilterPermanent; -import mage.filter.predicate.mageobject.CardTypePredicate; -import mage.game.Game; +import mage.filter.StaticFilters; import mage.target.TargetPermanent; import mage.target.common.TargetCardInHand; @@ -53,44 +51,25 @@ import mage.target.common.TargetCardInHand; * @author escplan9 (Derek Monturo - dmontur1 at gmail dot com) */ public class AlexiZephyrMage extends CardImpl { - - private final UUID originalId; - - private static final FilterPermanent filter = new FilterPermanent("Target creatures"); - - static { - filter.add(new CardTypePredicate(CardType.CREATURE)); - } public AlexiZephyrMage(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{U}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}{U}"); addSuperType(SuperType.LEGENDARY); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.SPELLSHAPER); this.power = new MageInt(3); this.toughness = new MageInt(3); - //TODO: Make ability properly copiable // {X}{U}, {tap}, Discard two cards: Return X target creatures to their owners' hands. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ReturnToHandTargetEffect(), new ManaCostsImpl("{X}{U}")); ability.addCost(new TapSourceCost()); ability.addCost(new DiscardTargetCost(new TargetCardInHand(2, new FilterCard("two cards")))); - this.addAbility(ability); - - originalId = ability.getOriginalId(); - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability.getOriginalId().equals(originalId)) { - ability.getTargets().clear(); - ability.addTarget(new TargetPermanent(ability.getManaCostsToPay().getX(), filter)); - } + ability.addTarget(new TargetPermanent(StaticFilters.FILTER_PERMANENT_CREATURES)); + this.addAbility(ability); } public AlexiZephyrMage(final AlexiZephyrMage card) { super(card); - this.originalId = card.originalId; } @Override diff --git a/Mage.Sets/src/mage/cards/a/AncientHellkite.java b/Mage.Sets/src/mage/cards/a/AncientHellkite.java index 13b83e4168..ce4ccc612f 100644 --- a/Mage.Sets/src/mage/cards/a/AncientHellkite.java +++ b/Mage.Sets/src/mage/cards/a/AncientHellkite.java @@ -40,10 +40,10 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Zone; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.permanent.ControllerIdPredicate; -import mage.game.Game; -import mage.target.common.TargetCreaturePermanent; +import mage.filter.FilterPermanent; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.filter.predicate.permanent.DefendingPlayerControlsPredicate; +import mage.target.TargetPermanent; /** * @@ -51,7 +51,12 @@ import mage.target.common.TargetCreaturePermanent; */ public class AncientHellkite extends CardImpl { - private final UUID originalId; + private static final FilterPermanent filter = new FilterPermanent("creature defending player controls"); + + static { + filter.add(new CardTypePredicate(CardType.CREATURE)); + filter.add(new DefendingPlayerControlsPredicate()); + } public AncientHellkite(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{R}{R}{R}"); @@ -60,29 +65,14 @@ public class AncientHellkite extends CardImpl { this.power = new MageInt(6); this.toughness = new MageInt(6); - //TODO: Make ability properly copiable this.addAbility(FlyingAbility.getInstance()); Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(1), new ManaCostsImpl("{R}"), SourceAttackingCondition.instance); - ability.addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature defending player controls"))); - originalId = ability.getOriginalId(); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } public AncientHellkite(final AncientHellkite card) { super(card); - this.originalId = card.originalId; - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability.getOriginalId().equals(originalId)) { - ability.getTargets().clear(); - FilterCreaturePermanent filter = new FilterCreaturePermanent("creature defending player controls"); - UUID defenderId = game.getCombat().getDefenderId(ability.getSourceId()); - filter.add(new ControllerIdPredicate(defenderId)); - TargetCreaturePermanent target = new TargetCreaturePermanent(filter); - ability.addTarget(target); - } } @Override diff --git a/Mage.Sets/src/mage/cards/a/ArcticNishoba.java b/Mage.Sets/src/mage/cards/a/ArcticNishoba.java index 556ed77f52..927961134a 100644 --- a/Mage.Sets/src/mage/cards/a/ArcticNishoba.java +++ b/Mage.Sets/src/mage/cards/a/ArcticNishoba.java @@ -30,6 +30,7 @@ package mage.cards.a; import java.util.UUID; import mage.MageInt; import mage.abilities.common.DiesTriggeredAbility; +import mage.abilities.costs.OrCost; import mage.constants.SubType; import mage.abilities.keyword.TrampleAbility; import mage.abilities.costs.mana.ManaCostsImpl; @@ -61,7 +62,11 @@ public class ArcticNishoba extends CardImpl { this.addAbility(TrampleAbility.getInstance()); // Cumulative upkeep {G} or {W} - this.addAbility(new CumulativeUpkeepAbility(new ManaCostsImpl("{G/W}"))); + this.addAbility(new CumulativeUpkeepAbility(new OrCost( + new ManaCostsImpl("{G}"), + new ManaCostsImpl("{W}"), + "{G} or {W}" + ))); // When Arctic Nishoba dies, you gain 2 life for each age counter on it. Effect effect = new GainLifeEffect(new MultipliedValue(new CountersSourceCount(CounterType.AGE), 2)); diff --git a/Mage.Sets/src/mage/cards/b/BloodstokeHowler.java b/Mage.Sets/src/mage/cards/b/BloodstokeHowler.java new file mode 100644 index 0000000000..5e183305c5 --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BloodstokeHowler.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.cards.b; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.TurnedFaceUpSourceTriggeredAbility; +import mage.constants.SubType; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.abilities.keyword.MorphAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; + +/** + * + * @author TheElk801 + */ +public class BloodstokeHowler extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Beast creatures you control"); + + static { + filter.add(new SubtypePredicate(SubType.BEAST)); + } + + public BloodstokeHowler(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{R}"); + + this.subtype.add(SubType.BEAST); + this.power = new MageInt(3); + this.toughness = new MageInt(4); + + // Morph {6}{R} + this.addAbility(new MorphAbility(this, new ManaCostsImpl("{6}{R}"))); + + // When Bloodstoke Howler is turned face up, Beast creatures you control get +3/+0 until end of turn. + this.addAbility(new TurnedFaceUpSourceTriggeredAbility(new BoostControlledEffect(3, 0, Duration.EndOfTurn, filter))); + } + + public BloodstokeHowler(final BloodstokeHowler card) { + super(card); + } + + @Override + public BloodstokeHowler copy() { + return new BloodstokeHowler(this); + } +} diff --git a/Mage.Sets/src/mage/cards/b/BorosReckoner.java b/Mage.Sets/src/mage/cards/b/BorosReckoner.java index 92d81ac125..54a67621c9 100644 --- a/Mage.Sets/src/mage/cards/b/BorosReckoner.java +++ b/Mage.Sets/src/mage/cards/b/BorosReckoner.java @@ -51,20 +51,20 @@ import mage.target.common.TargetCreatureOrPlayer; public class BorosReckoner extends CardImpl { public BorosReckoner(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{R/W}{R/W}{R/W}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{R/W}{R/W}{R/W}"); this.subtype.add(SubType.MINOTAUR, SubType.WIZARD); this.power = new MageInt(3); this.toughness = new MageInt(3); // Whenever Boros Reckoner is dealt damage, it deals that much damage to target creature or player. - Ability ability = new DealtDamageToSourceTriggeredAbility(Zone.BATTLEFIELD, new BorosReckonerDealDamageEffect(), false); + Ability ability = new DealtDamageToSourceTriggeredAbility(Zone.BATTLEFIELD, new BorosReckonerDealDamageEffect(), false, false, true); ability.addTarget(new TargetCreatureOrPlayer()); this.addAbility(ability); // {R/W}: Boros Reckoner gains first strike until end of turn. this.addAbility(new SimpleActivatedAbility( - Zone.BATTLEFIELD, new GainAbilitySourceEffect(FirstStrikeAbility.getInstance(),Duration.EndOfTurn), new ManaCostsImpl("{R/W}"))); + Zone.BATTLEFIELD, new GainAbilitySourceEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn), new ManaCostsImpl("{R/W}"))); } public BorosReckoner(final BorosReckoner card) { diff --git a/Mage.Sets/src/mage/cards/b/BroodhatchNantuko.java b/Mage.Sets/src/mage/cards/b/BroodhatchNantuko.java index 11bf446387..72bf9a42a3 100644 --- a/Mage.Sets/src/mage/cards/b/BroodhatchNantuko.java +++ b/Mage.Sets/src/mage/cards/b/BroodhatchNantuko.java @@ -52,13 +52,13 @@ import mage.players.Player; public class BroodhatchNantuko extends CardImpl { public BroodhatchNantuko(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}"); this.subtype.add(SubType.INSECT, SubType.DRUID); this.power = new MageInt(1); this.toughness = new MageInt(1); // Whenever Broodhatch Nantuko is dealt damage, you may create that many 1/1 green Insect creature tokens. - this.addAbility(new DealtDamageToSourceTriggeredAbility(Zone.BATTLEFIELD, new BroodhatchNantukoDealDamageEffect(), true)); + this.addAbility(new DealtDamageToSourceTriggeredAbility(Zone.BATTLEFIELD, new BroodhatchNantukoDealDamageEffect(), true, false, true)); // Morph {2}{G} this.addAbility(new MorphAbility(this, new ManaCostsImpl("{2}{G}"))); } @@ -100,4 +100,4 @@ class BroodhatchNantukoDealDamageEffect extends OneShotEffect { } return false; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/c/CandelabraOfTawnos.java b/Mage.Sets/src/mage/cards/c/CandelabraOfTawnos.java index 2d85919813..4cbab1c4fc 100644 --- a/Mage.Sets/src/mage/cards/c/CandelabraOfTawnos.java +++ b/Mage.Sets/src/mage/cards/c/CandelabraOfTawnos.java @@ -37,10 +37,10 @@ import mage.abilities.effects.common.UntapTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.TargetAdjustment; import mage.constants.Zone; -import mage.filter.common.FilterLandPermanent; -import mage.game.Game; -import mage.target.common.TargetLandPermanent; +import mage.filter.StaticFilters; +import mage.target.TargetPermanent; /** * @@ -48,33 +48,21 @@ import mage.target.common.TargetLandPermanent; */ public class CandelabraOfTawnos extends CardImpl { - private final UUID originalId; - public CandelabraOfTawnos(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{1}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}"); - //TODO: Make ability properly copiable // {X}, {T}: Untap X target lands. Effect effect = new UntapTargetEffect(); effect.setText("untap X target lands"); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl("{X}")); ability.addCost(new TapSourceCost()); - originalId = ability.getOriginalId(); + ability.addTarget(new TargetPermanent(StaticFilters.FILTER_LANDS)); + ability.setTargetAdjustment(TargetAdjustment.X_TARGETS); this.addAbility(ability); } - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability.getOriginalId().equals(originalId)){ - int xValue = ability.getManaCostsToPay().getX(); - ability.getTargets().clear(); - ability.addTarget(new TargetLandPermanent(xValue, xValue, new FilterLandPermanent(), false)); - } - } - public CandelabraOfTawnos(final CandelabraOfTawnos card) { super(card); - this.originalId = card.originalId; } @Override diff --git a/Mage.Sets/src/mage/cards/c/CoalhaulerSwine.java b/Mage.Sets/src/mage/cards/c/CoalhaulerSwine.java index 91720d3b2d..6508d432b0 100644 --- a/Mage.Sets/src/mage/cards/c/CoalhaulerSwine.java +++ b/Mage.Sets/src/mage/cards/c/CoalhaulerSwine.java @@ -49,14 +49,14 @@ public class CoalhaulerSwine extends CardImpl { public CoalhaulerSwine(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{R}{R}"); - + this.subtype.add(SubType.BOAR); this.subtype.add(SubType.BEAST); this.power = new MageInt(4); this.toughness = new MageInt(4); // Whenever Coalhauler Swine is dealt damage, it deals that much damage to each player. - this.addAbility(new DealtDamageToSourceTriggeredAbility(Zone.BATTLEFIELD, new CoalhaulerSwineEffect(), false)); + this.addAbility(new DealtDamageToSourceTriggeredAbility(Zone.BATTLEFIELD, new CoalhaulerSwineEffect(), false, false, true)); } public CoalhaulerSwine(final CoalhaulerSwine card) { @@ -88,7 +88,7 @@ public class CoalhaulerSwine extends CardImpl { public boolean apply(Game game, Ability source) { for (UUID playerId : game.getPlayers().keySet()) { Player player = game.getPlayer(playerId); - if(player != null) { + if (player != null) { player.damage((Integer) this.getValue("damage"), source.getSourceId(), game, false, true); } } diff --git a/Mage.Sets/src/mage/cards/c/CrownOfDoom.java b/Mage.Sets/src/mage/cards/c/CrownOfDoom.java index f5417c9a11..851c8ecd92 100644 --- a/Mage.Sets/src/mage/cards/c/CrownOfDoom.java +++ b/Mage.Sets/src/mage/cards/c/CrownOfDoom.java @@ -39,15 +39,15 @@ import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.abilities.effects.common.continuous.GainControlTargetEffect; -import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; import mage.filter.FilterPlayer; import mage.filter.StaticFilters; -import mage.filter.predicate.Predicates; -import mage.filter.predicate.other.PlayerIdPredicate; +import mage.filter.predicate.ObjectSourcePlayer; +import mage.filter.predicate.ObjectSourcePlayerPredicate; import mage.game.Game; +import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.TargetPlayer; import mage.target.targetpointer.FixedTarget; @@ -58,7 +58,11 @@ import mage.target.targetpointer.FixedTarget; */ public class CrownOfDoom extends CardImpl { - private UUID abilityId; + private static final FilterPlayer filter = new FilterPlayer("player other than {this}'s owner"); + + static { + filter.add(new CrownOfDoomPredicate()); + } public CrownOfDoom(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); @@ -71,27 +75,12 @@ public class CrownOfDoom extends CardImpl { //TODO: Make ability properly copiable // {2}: Target player other than Crown of Doom's owner gains control of it. Activate this ability only during your turn. Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, new CrownOfDoomEffect(), new ManaCostsImpl("{2}"), MyTurnCondition.instance); - ability.addTarget(new TargetPlayer(1, 1, false, new FilterPlayer("player other than Crown of Doom's owner"))); - abilityId = ability.getOriginalId(); + ability.addTarget(new TargetPlayer(1, 1, false, filter)); this.addAbility(ability); } - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability.getOriginalId().equals(abilityId)) { - Card sourceCard = game.getCard(ability.getSourceId()); - if (sourceCard != null) { - ability.getTargets().clear(); - FilterPlayer filter = new FilterPlayer("player other than " + sourceCard.getIdName() + "'s owner"); - filter.add(Predicates.not(new PlayerIdPredicate(sourceCard.getOwnerId()))); - ability.addTarget(new TargetPlayer(1, 1, false, filter)); - } - } - } - public CrownOfDoom(final CrownOfDoom card) { super(card); - this.abilityId = card.abilityId; } @Override @@ -100,6 +89,27 @@ public class CrownOfDoom extends CardImpl { } } +class CrownOfDoomPredicate implements ObjectSourcePlayerPredicate> { + + public CrownOfDoomPredicate() { + } + + @Override + public boolean apply(ObjectSourcePlayer input, Game game) { + Player targetPlayer = input.getObject(); + Permanent sourceObject = game.getPermanentOrLKIBattlefield(input.getSourceId()); + if (targetPlayer == null || sourceObject == null) { + return false; + } + return !targetPlayer.getId().equals(sourceObject.getOwnerId()); + } + + @Override + public String toString() { + return "Owner(" + ')'; + } +} + class CrownOfDoomEffect extends OneShotEffect { public CrownOfDoomEffect() { diff --git a/Mage.Sets/src/mage/cards/d/DeclarationOfNaught.java b/Mage.Sets/src/mage/cards/d/DeclarationOfNaught.java index b0fb8f6405..da4dd1c605 100644 --- a/Mage.Sets/src/mage/cards/d/DeclarationOfNaught.java +++ b/Mage.Sets/src/mage/cards/d/DeclarationOfNaught.java @@ -28,7 +28,6 @@ package mage.cards.d; import java.util.UUID; -import mage.abilities.Ability; import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.ManaCostsImpl; @@ -37,10 +36,9 @@ import mage.abilities.effects.common.NameACardEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.TargetAdjustment; import mage.constants.Zone; import mage.filter.FilterSpell; -import mage.filter.predicate.mageobject.NamePredicate; -import mage.game.Game; import mage.target.TargetSpell; /** @@ -49,38 +47,23 @@ import mage.target.TargetSpell; */ public class DeclarationOfNaught extends CardImpl { - private final UUID originalId; static final private FilterSpell filter = new FilterSpell("spell with the chosen name"); public DeclarationOfNaught(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{U}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{U}{U}"); // As Declaration of Naught enters the battlefield, name a card. this.addAbility(new AsEntersBattlefieldAbility(new NameACardEffect(NameACardEffect.TypeOfName.ALL))); - //TODO: Make ability properly copiable // {U}: Counter target spell with the chosen name. SimpleActivatedAbility ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CounterTargetEffect(), new ManaCostsImpl("{U}")); + ability.setTargetAdjustment(TargetAdjustment.CHOSEN_NAME); ability.addTarget(new TargetSpell(filter)); - originalId = ability.getOriginalId(); this.addAbility(ability); - - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability.getOriginalId().equals(originalId)) { - ability.getTargets().clear(); - FilterSpell filter2 = new FilterSpell("spell with the chosen name"); - filter2.add(new NamePredicate((String) game.getState().getValue(ability.getSourceId().toString() + NameACardEffect.INFO_KEY))); - TargetSpell target = new TargetSpell(1, filter2); - ability.addTarget(target); - } } public DeclarationOfNaught(final DeclarationOfNaught card) { super(card); - this.originalId = card.originalId; } @Override diff --git a/Mage.Sets/src/mage/cards/d/DeepfireElemental.java b/Mage.Sets/src/mage/cards/d/DeepfireElemental.java index 60ed530eb7..331de2866f 100644 --- a/Mage.Sets/src/mage/cards/d/DeepfireElemental.java +++ b/Mage.Sets/src/mage/cards/d/DeepfireElemental.java @@ -37,14 +37,11 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.ComparisonType; +import mage.constants.TargetAdjustment; import mage.constants.Zone; import mage.filter.FilterPermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.CardTypePredicate; -import mage.filter.predicate.mageobject.ConvertedManaCostPredicate; -import mage.game.Game; -import mage.target.Target; import mage.target.TargetPermanent; /** @@ -53,44 +50,31 @@ import mage.target.TargetPermanent; */ public class DeepfireElemental extends CardImpl { - private final UUID originalId; - private static final FilterPermanent filter = new FilterPermanent("artifact or creature with converted mana cost X"); static { - filter.add(Predicates.or(new CardTypePredicate(CardType.ARTIFACT), new CardTypePredicate(CardType.CREATURE))); + filter.add(Predicates.or( + new CardTypePredicate(CardType.ARTIFACT), + new CardTypePredicate(CardType.CREATURE) + )); } public DeepfireElemental(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{B}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{B}{R}"); this.subtype.add(SubType.ELEMENTAL); this.power = new MageInt(4); this.toughness = new MageInt(4); - //TODO: Make ability properly copiable // {X}{X}{1}: Destroy target artifact or creature with converted mana cost X. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DestroyTargetEffect(), new ManaCostsImpl("{X}{X}{1}")); ability.addTarget(new TargetPermanent(filter)); - originalId = ability.getOriginalId(); + ability.setTargetAdjustment(TargetAdjustment.X_CMC_EQUAL_PERM); this.addAbility(ability); } - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability.getOriginalId().equals(originalId)) { - ability.getTargets().clear(); - FilterPermanent newFilter = filter.copy(); - newFilter.setMessage(new StringBuilder("artifact or creature with converted mana cost {").append(ability.getManaCostsToPay().getX()).append('}').toString()); - newFilter.add(new ConvertedManaCostPredicate(ComparisonType.EQUAL_TO, ability.getManaCostsToPay().getX())); - Target target = new TargetPermanent(newFilter); - ability.addTarget(target); - } - } - public DeepfireElemental(final DeepfireElemental card) { super(card); - this.originalId = card.originalId; } @Override diff --git a/Mage.Sets/src/mage/cards/e/EldraziDisplacer.java b/Mage.Sets/src/mage/cards/e/EldraziDisplacer.java index 37ac9854bc..ceaa7cfbf9 100644 --- a/Mage.Sets/src/mage/cards/e/EldraziDisplacer.java +++ b/Mage.Sets/src/mage/cards/e/EldraziDisplacer.java @@ -71,7 +71,7 @@ public class EldraziDisplacer extends CardImpl { effect.setText("Exile another target creature"); effect.setApplyEffectsAfter(); // Needed to let temporary continuous effects end if a permanent is blinked Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl<>("{2}{C}")); - effect = new ReturnToBattlefieldUnderOwnerControlTargetEffect(true, true); + effect = new ReturnToBattlefieldUnderOwnerControlTargetEffect(true); effect.setText(", then return it to the battlefield tapped under its owner's control"); ability.addEffect(effect); ability.addTarget(new TargetCreaturePermanent(FILTER)); diff --git a/Mage.Sets/src/mage/cards/e/ElephantResurgence.java b/Mage.Sets/src/mage/cards/e/ElephantResurgence.java new file mode 100644 index 0000000000..203780628f --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/ElephantResurgence.java @@ -0,0 +1,97 @@ +/* + * 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.cards.e; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateTokenTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.game.Game; +import mage.game.permanent.token.ElephantResurgenceToken; +import mage.players.Player; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author TheElk801 + */ +public class ElephantResurgence extends CardImpl { + + public ElephantResurgence(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{G}"); + + // Each player creates a green Elephant creature token. Those creatures have "This creature's power and toughness are each equal to the number of creature cards in its controller's graveyard." + this.getSpellAbility().addEffect(new ElephantResurgenceEffect()); + } + + public ElephantResurgence(final ElephantResurgence card) { + super(card); + } + + @Override + public ElephantResurgence copy() { + return new ElephantResurgence(this); + } +} + +class ElephantResurgenceEffect extends OneShotEffect { + + public ElephantResurgenceEffect() { + super(Outcome.Detriment); + this.staticText = "Each player creates a green Elephant creature token. Those creatures have " + + "\"This creature's power and toughness are each equal to the number of creature cards in its controller's graveyard.\""; + } + + public ElephantResurgenceEffect(final ElephantResurgenceEffect effect) { + super(effect); + } + + @Override + public ElephantResurgenceEffect copy() { + return new ElephantResurgenceEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { + Effect effect = new CreateTokenTargetEffect(new ElephantResurgenceToken(), 1); + effect.setTargetPointer(new FixedTarget(playerId)); + effect.apply(game, source); + } + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/e/Embolden.java b/Mage.Sets/src/mage/cards/e/Embolden.java new file mode 100644 index 0000000000..be8ebffa0d --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/Embolden.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.cards.e; + +import java.util.UUID; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.PreventDamageToTargetMultiAmountEffect; +import mage.abilities.keyword.FlashbackAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.TimingRule; +import mage.target.common.TargetCreatureOrPlayerAmount; + +/** + * + * @author TheElk801 + */ +public class Embolden extends CardImpl { + + public Embolden(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{W}"); + + // Prevent the next 4 damage that would be dealt this turn to any number of target creatures and/or players, divided as you choose. + this.getSpellAbility().addEffect(new PreventDamageToTargetMultiAmountEffect(Duration.EndOfTurn, 4)); + this.getSpellAbility().addTarget(new TargetCreatureOrPlayerAmount(4)); + + // Flashback {1}{W} + this.addAbility(new FlashbackAbility(new ManaCostsImpl("{1}{W}"), TimingRule.INSTANT)); + + } + + public Embolden(final Embolden card) { + super(card); + } + + @Override + public Embolden copy() { + return new Embolden(this); + } +} diff --git a/Mage.Sets/src/mage/cards/f/FelidarGuardian.java b/Mage.Sets/src/mage/cards/f/FelidarGuardian.java index ed85699756..c7acc317d9 100644 --- a/Mage.Sets/src/mage/cards/f/FelidarGuardian.java +++ b/Mage.Sets/src/mage/cards/f/FelidarGuardian.java @@ -66,7 +66,7 @@ public class FelidarGuardian extends CardImpl { Effect effect = new ExileTargetForSourceEffect(); effect.setApplyEffectsAfter(); Ability ability = new EntersBattlefieldTriggeredAbility(effect, true); - ability.addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, true)); + ability.addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect()); ability.addTarget(new TargetControlledPermanent(filter)); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/f/FiredrinkerSatyr.java b/Mage.Sets/src/mage/cards/f/FiredrinkerSatyr.java index 0e133b27c9..e7e045dd2d 100644 --- a/Mage.Sets/src/mage/cards/f/FiredrinkerSatyr.java +++ b/Mage.Sets/src/mage/cards/f/FiredrinkerSatyr.java @@ -54,7 +54,7 @@ import mage.players.Player; public class FiredrinkerSatyr extends CardImpl { public FiredrinkerSatyr(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{R}"); this.subtype.add(SubType.SATYR); this.subtype.add(SubType.SHAMAN); @@ -62,9 +62,9 @@ public class FiredrinkerSatyr extends CardImpl { this.toughness = new MageInt(1); // Whenever Firedrinker Satyr is dealt damage, it deals that much damage to you. - this.addAbility(new DealtDamageToSourceTriggeredAbility(Zone.BATTLEFIELD, new FiredrinkerSatyrDealDamageEffect(), false)); + this.addAbility(new DealtDamageToSourceTriggeredAbility(Zone.BATTLEFIELD, new FiredrinkerSatyrDealDamageEffect(), false, false, true)); // {1}{R}: Firedrinker Satyr gets +1/+0 until end of turn and deals 1 damage to you. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostSourceEffect(1,0, Duration.EndOfTurn), new ManaCostsImpl("{1}{R}")); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostSourceEffect(1, 0, Duration.EndOfTurn), new ManaCostsImpl("{1}{R}")); Effect effect = new DamageControllerEffect(1); effect.setText("and deals 1 damage to you"); ability.addEffect(effect); diff --git a/Mage.Sets/src/mage/cards/f/FloodwaterDam.java b/Mage.Sets/src/mage/cards/f/FloodwaterDam.java index 10f6e12d9b..fad71572e0 100644 --- a/Mage.Sets/src/mage/cards/f/FloodwaterDam.java +++ b/Mage.Sets/src/mage/cards/f/FloodwaterDam.java @@ -38,43 +38,29 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Zone; -import mage.filter.common.FilterLandPermanent; -import mage.game.Game; -import mage.target.common.TargetLandPermanent; +import mage.filter.StaticFilters; +import mage.target.TargetPermanent; /** * * @author fireshoes */ public class FloodwaterDam extends CardImpl { - - private final UUID originalId; public FloodwaterDam(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{3}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); - //TODO: Make ability properly copiable // {X}{X}{1}, {tap}: Tap X target lands. Effect effect = new TapTargetEffect(); effect.setText("tap X target lands"); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl("{X}{X}{1}")); ability.addCost(new TapSourceCost()); - originalId = ability.getOriginalId(); + ability.addTarget(new TargetPermanent(StaticFilters.FILTER_LANDS)); this.addAbility(ability); } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability.getOriginalId().equals(originalId)){ - int xValue = ability.getManaCostsToPay().getX(); - ability.getTargets().clear(); - ability.addTarget(new TargetLandPermanent(xValue, xValue, new FilterLandPermanent(), false)); - } - } public FloodwaterDam(final FloodwaterDam card) { super(card); - this.originalId = card.originalId; } @Override diff --git a/Mage.Sets/src/mage/cards/g/GethLordOfTheVault.java b/Mage.Sets/src/mage/cards/g/GethLordOfTheVault.java index 2972eaff42..e375d2631d 100644 --- a/Mage.Sets/src/mage/cards/g/GethLordOfTheVault.java +++ b/Mage.Sets/src/mage/cards/g/GethLordOfTheVault.java @@ -39,17 +39,15 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.ComparisonType; import mage.constants.Outcome; import mage.constants.SuperType; +import mage.constants.TargetAdjustment; import mage.constants.Zone; import mage.filter.FilterCard; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.CardTypePredicate; -import mage.filter.predicate.mageobject.ConvertedManaCostPredicate; import mage.game.Game; import mage.players.Player; -import mage.target.Target; import mage.target.common.TargetCardInOpponentsGraveyard; /** @@ -57,7 +55,13 @@ import mage.target.common.TargetCardInOpponentsGraveyard; */ public class GethLordOfTheVault extends CardImpl { - private final UUID originalId; + private static final FilterCard filter = new FilterCard("artifact or creature card with converted mana cost X from an opponent's graveyard"); + + static { + filter.add(Predicates.or( + new CardTypePredicate(CardType.ARTIFACT), + new CardTypePredicate(CardType.CREATURE))); + } public GethLordOfTheVault(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{B}{B}"); @@ -69,33 +73,16 @@ public class GethLordOfTheVault extends CardImpl { // Intimidate this.addAbility(IntimidateAbility.getInstance()); - //TODO: Make ability properly copiable // {X}{B}: Put target artifact or creature card with converted mana cost X from an opponent's graveyard onto the battlefield under your control tapped. // Then that player puts the top X cards of his or her library into his or her graveyard. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new GethLordOfTheVaultEffect(), new ManaCostsImpl("{X}{B}")); - originalId = ability.getOriginalId(); - ability.addTarget(new TargetCardInOpponentsGraveyard(new FilterCard("artifact or creature card with converted mana cost X from an opponent's graveyard"))); + ability.setTargetAdjustment(TargetAdjustment.X_CMC_EQUAL_GY_CARD); + ability.addTarget(new TargetCardInOpponentsGraveyard(filter)); this.addAbility(ability); } - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability.getOriginalId().equals(originalId)) { - int xValue = ability.getManaCostsToPay().getX(); - ability.getTargets().clear(); - FilterCard filter = new FilterCard("artifact or creature card with converted mana cost " + xValue + " from an opponent's graveyard"); - filter.add(Predicates.or( - new CardTypePredicate(CardType.ARTIFACT), - new CardTypePredicate(CardType.CREATURE))); - filter.add(new ConvertedManaCostPredicate(ComparisonType.EQUAL_TO, xValue)); - Target target = new TargetCardInOpponentsGraveyard(filter); - ability.addTarget(target); - } - } - public GethLordOfTheVault(final GethLordOfTheVault card) { super(card); - this.originalId = card.originalId; } @Override diff --git a/Mage.Sets/src/mage/cards/g/GorillaShaman.java b/Mage.Sets/src/mage/cards/g/GorillaShaman.java index 96ce257d6f..751fed34d6 100644 --- a/Mage.Sets/src/mage/cards/g/GorillaShaman.java +++ b/Mage.Sets/src/mage/cards/g/GorillaShaman.java @@ -37,14 +37,11 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.ComparisonType; +import mage.constants.TargetAdjustment; import mage.constants.Zone; -import mage.filter.common.FilterArtifactPermanent; +import mage.filter.FilterPermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.CardTypePredicate; -import mage.filter.predicate.mageobject.ConvertedManaCostPredicate; -import mage.game.Game; -import mage.target.Target; import mage.target.TargetPermanent; /** @@ -53,39 +50,29 @@ import mage.target.TargetPermanent; */ public class GorillaShaman extends CardImpl { - private final UUID originalId; + private static final FilterPermanent filter = new FilterPermanent("noncreature artifact with converted mana cost X"); + + static { + filter.add(new CardTypePredicate(CardType.ARTIFACT)); + filter.add(Predicates.not(new CardTypePredicate(CardType.CREATURE))); + } public GorillaShaman(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{R}"); this.subtype.add(SubType.APE); this.subtype.add(SubType.SHAMAN); this.power = new MageInt(1); this.toughness = new MageInt(1); - //TODO: Make ability properly copiable // {X}{X}{1}: Destroy target noncreature artifact with converted mana cost X. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DestroyTargetEffect(), new ManaCostsImpl("{X}{X}{1}")); - ability.addTarget(new TargetPermanent(new FilterArtifactPermanent("noncreature artifact with converted mana cost X"))); - originalId = ability.getOriginalId(); + ability.addTarget(new TargetPermanent(filter)); + ability.setTargetAdjustment(TargetAdjustment.X_CMC_EQUAL_PERM); this.addAbility(ability); } - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability.getOriginalId().equals(originalId)) { - int xValue = ability.getManaCostsToPay().getX(); - ability.getTargets().clear(); - FilterArtifactPermanent filter = new FilterArtifactPermanent(new StringBuilder("noncreature artifact with converted mana cost ").append(xValue).toString()); - filter.add(new ConvertedManaCostPredicate(ComparisonType.EQUAL_TO, xValue)); - filter.add(Predicates.not(new CardTypePredicate(CardType.CREATURE))); - Target target = new TargetPermanent(filter); - ability.addTarget(target); - } - } - public GorillaShaman(final GorillaShaman card) { super(card); - this.originalId = card.originalId; } @Override diff --git a/Mage.Sets/src/mage/cards/g/GrimCaptainsCall.java b/Mage.Sets/src/mage/cards/g/GrimCaptainsCall.java index e5c2ffc7ce..df3bb98dff 100644 --- a/Mage.Sets/src/mage/cards/g/GrimCaptainsCall.java +++ b/Mage.Sets/src/mage/cards/g/GrimCaptainsCall.java @@ -96,9 +96,9 @@ class GrimCaptainsCallEffect extends OneShotEffect { } private void returnToHand(Game game, SubType subType, Player controller, Ability source) { - FilterCreatureCard filter = new FilterCreatureCard(); + FilterCreatureCard filter = new FilterCreatureCard(subType.getDescription() + " card"); filter.add(new SubtypePredicate(subType)); - TargetCardInYourGraveyard target = new TargetCardInYourGraveyard(new FilterCreatureCard()); + TargetCardInYourGraveyard target = new TargetCardInYourGraveyard(new FilterCreatureCard(filter)); if (target.canChoose(source.getSourceId(), source.getControllerId(), game)) { if (controller.chooseTarget(outcome, target, source, game)) { Card card = game.getCard(target.getFirstTarget()); diff --git a/Mage.Sets/src/mage/cards/h/HakimLoreweaver.java b/Mage.Sets/src/mage/cards/h/HakimLoreweaver.java index 1b3082b518..ba3efa7f1d 100644 --- a/Mage.Sets/src/mage/cards/h/HakimLoreweaver.java +++ b/Mage.Sets/src/mage/cards/h/HakimLoreweaver.java @@ -46,6 +46,7 @@ import mage.constants.Outcome; import mage.constants.PhaseStep; import mage.constants.SubType; import mage.constants.SuperType; +import mage.constants.TargetController; import mage.constants.Zone; import mage.filter.FilterCard; import mage.filter.FilterPermanent; @@ -53,6 +54,7 @@ import mage.filter.predicate.mageobject.CardIdPredicate; import mage.filter.predicate.mageobject.CardTypePredicate; import mage.filter.predicate.mageobject.SubtypePredicate; import mage.filter.predicate.other.AuraCardCanAttachToPermanentId; +import mage.filter.predicate.other.OwnerPredicate; import mage.filter.predicate.permanent.AttachedToPredicate; import mage.game.Game; import mage.game.permanent.Permanent; @@ -62,12 +64,17 @@ import mage.target.common.TargetCardInYourGraveyard; /** * - * @author jeffwadsworth + * @author jeffwadsworth, TheElk801 */ public class HakimLoreweaver extends CardImpl { - private final static String rule = "Return target Aura card from your graveyard to the battlefield attached to Hakim, Loreweaver. Activate this ability only during your upkeep and only if Hakim isn't enchanted."; - UUID originalId; + private static final FilterCard filter = new FilterCard("target Aura card from your graveyard"); + + static { + filter.add(new CardTypePredicate(CardType.ENCHANTMENT)); + filter.add(new SubtypePredicate(SubType.AURA)); + filter.add(new OwnerPredicate(TargetController.YOU)); + } public HakimLoreweaver(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}"); @@ -81,11 +88,13 @@ public class HakimLoreweaver extends CardImpl { // Flying this.addAbility(FlyingAbility.getInstance()); - //TODO: Make ability properly copiable // {U}{U}: Return target Aura card from your graveyard to the battlefield attached to Hakim, Loreweaver. Activate this ability only during your upkeep and only if Hakim isn't enchanted. - Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, new HakimLoreweaverEffect(), new ManaCostsImpl("{U}{U}"), new HakimLoreweaverCondition(), rule); - ability.addTarget(new TargetCardInYourGraveyard()); - originalId = ability.getOriginalId(); + Ability ability = new ConditionalActivatedAbility( + Zone.BATTLEFIELD, + new HakimLoreweaverEffect(), + new ManaCostsImpl("{U}{U}"), + new HakimLoreweaverCondition()); + ability.addTarget(new TargetCardInYourGraveyard(filter)); this.addAbility(ability); // {U}{U}, {tap}: Destroy all Auras attached to Hakim. @@ -101,26 +110,8 @@ public class HakimLoreweaver extends CardImpl { } - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability.getOriginalId().equals(originalId)) { - Player controller = game.getPlayer(ability.getControllerId()); - if (controller != null) { - ability.getTargets().clear(); - FilterCard filterAuraCard = new FilterCard("target Aura card from your graveyard"); - filterAuraCard.add(new CardTypePredicate(CardType.ENCHANTMENT)); - filterAuraCard.add(new SubtypePredicate(SubType.AURA)); - filterAuraCard.add(new AuraCardCanAttachToPermanentId(ability.getSourceId())); - TargetCardInYourGraveyard target = new TargetCardInYourGraveyard(filterAuraCard); - ability.addTarget(target); - } - } - - } - public HakimLoreweaver(final HakimLoreweaver card) { super(card); - this.originalId = card.originalId; } @Override @@ -133,7 +124,7 @@ class HakimLoreweaverEffect extends OneShotEffect { public HakimLoreweaverEffect() { super(Outcome.Benefit); - this.staticText = "Return target Aura card from your graveyard to the battlefield attached to {this}. Activate this ability only during your upkeep and only if Hakim isn't enchanted"; + this.staticText = "Return target Aura card from your graveyard to the battlefield attached to {this}."; } public HakimLoreweaverEffect(final HakimLoreweaverEffect effect) { @@ -153,7 +144,8 @@ class HakimLoreweaverEffect extends OneShotEffect { if (controller != null && hakimLoreweaver != null && controller.canRespond() - && targetAuraCard != null) { + && targetAuraCard != null + && new AuraCardCanAttachToPermanentId(hakimLoreweaver.getId()).apply(targetAuraCard, game)) { Target target = targetAuraCard.getSpellAbility().getTargets().get(0); if (target != null) { game.getState().setValue("attachTo:" + targetAuraCard.getId(), hakimLoreweaver); @@ -188,4 +180,9 @@ class HakimLoreweaverCondition implements Condition { } return false; } + + @Override + public String toString() { + return "only during your upkeep and only if {this} isn't enchanted"; + } } diff --git a/Mage.Sets/src/mage/cards/h/HearthKami.java b/Mage.Sets/src/mage/cards/h/HearthKami.java index 636785d695..40d3cf2b6d 100644 --- a/Mage.Sets/src/mage/cards/h/HearthKami.java +++ b/Mage.Sets/src/mage/cards/h/HearthKami.java @@ -38,12 +38,10 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.ComparisonType; +import mage.constants.TargetAdjustment; import mage.constants.Zone; -import mage.filter.common.FilterArtifactPermanent; -import mage.filter.predicate.mageobject.ConvertedManaCostPredicate; -import mage.game.Game; -import mage.target.Target; +import mage.filter.FilterPermanent; +import mage.filter.predicate.mageobject.CardTypePredicate; import mage.target.TargetPermanent; /** @@ -51,7 +49,11 @@ import mage.target.TargetPermanent; */ public class HearthKami extends CardImpl { - private final UUID originalId; + private static final FilterPermanent filter = new FilterPermanent("artifact with converted mana cost X"); + + static { + filter.add(new CardTypePredicate(CardType.ARTIFACT)); + } public HearthKami(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}"); @@ -60,30 +62,16 @@ public class HearthKami extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(1); - //TODO: Make ability properly copiable // {X}, Sacrifice Hearth Kami: Destroy target artifact with converted mana cost X. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DestroyTargetEffect(), new ManaCostsImpl("{X}")); ability.addCost(new SacrificeSourceCost()); - ability.addTarget(new TargetPermanent(new FilterArtifactPermanent("artifact with converted mana cost X"))); - originalId = ability.getOriginalId(); + ability.addTarget(new TargetPermanent(filter)); + ability.setTargetAdjustment(TargetAdjustment.X_CMC_EQUAL_PERM); this.addAbility(ability); } - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability.getOriginalId().equals(originalId)) { - int xValue = ability.getManaCostsToPay().getX(); - ability.getTargets().clear(); - FilterArtifactPermanent filter = new FilterArtifactPermanent(new StringBuilder("artifact with converted mana cost ").append(xValue).toString()); - filter.add(new ConvertedManaCostPredicate(ComparisonType.EQUAL_TO, xValue)); - Target target = new TargetPermanent(filter); - ability.addTarget(target); - } - } - public HearthKami(final HearthKami card) { super(card); - this.originalId = card.originalId; } @Override diff --git a/Mage.Sets/src/mage/cards/h/HopeOfGhirapur.java b/Mage.Sets/src/mage/cards/h/HopeOfGhirapur.java index 7111d06e4d..9bfc1de65a 100644 --- a/Mage.Sets/src/mage/cards/h/HopeOfGhirapur.java +++ b/Mage.Sets/src/mage/cards/h/HopeOfGhirapur.java @@ -33,6 +33,7 @@ import java.util.Set; import java.util.UUID; import mage.MageInt; import mage.MageObject; +import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.SacrificeSourceCost; @@ -49,6 +50,8 @@ import mage.game.Game; import mage.game.events.DamagedPlayerEvent; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; +import mage.game.stack.StackAbility; +import mage.game.stack.StackObject; import mage.players.Player; import mage.target.TargetPlayer; import mage.watchers.Watcher; @@ -115,7 +118,7 @@ class HopeOfGhirapurCantCastEffect extends ContinuousRuleModifyingEffectImpl { @Override public String getInfoMessage(Ability source, GameEvent event, Game game) { - MageObject mageObject = game.getObject(source.getSourceId()); + MageObject mageObject = source.getSourceObject(game); if (mageObject != null) { return "You can't cast noncreature spells this turn (you were dealt damage by " + mageObject.getLogName() + ')'; } @@ -153,7 +156,7 @@ class HopeOfGhirapurPlayerLostLifePredicate implements ObjectSourcePlayerPredica } HopeOfGhirapurCombatDamageWatcher watcher = (HopeOfGhirapurCombatDamageWatcher) game.getState().getWatchers().get(HopeOfGhirapurCombatDamageWatcher.class.getSimpleName()); if (watcher != null) { - return watcher.playerGotCombatDamage(input.getSourceId(), input.getObject().getId()); + return watcher.playerGotCombatDamage(input.getSourceId(), input.getObject().getId(), game); } return false; } @@ -161,7 +164,7 @@ class HopeOfGhirapurPlayerLostLifePredicate implements ObjectSourcePlayerPredica class HopeOfGhirapurCombatDamageWatcher extends Watcher { - private final HashMap> combatDamagedPlayers = new HashMap<>(); + private final HashMap> combatDamagedPlayers = new HashMap<>(); public HopeOfGhirapurCombatDamageWatcher() { super(HopeOfGhirapurCombatDamageWatcher.class.getSimpleName(), WatcherScope.GAME); @@ -169,10 +172,10 @@ class HopeOfGhirapurCombatDamageWatcher extends Watcher { public HopeOfGhirapurCombatDamageWatcher(final HopeOfGhirapurCombatDamageWatcher watcher) { super(watcher); - for (UUID damagerId : watcher.combatDamagedPlayers.keySet()) { + for (MageObjectReference damager : watcher.combatDamagedPlayers.keySet()) { Set players = new HashSet<>(); - players.addAll(watcher.combatDamagedPlayers.get(damagerId)); - this.combatDamagedPlayers.put(damagerId, players); + players.addAll(watcher.combatDamagedPlayers.get(damager)); + this.combatDamagedPlayers.put(damager, players); } } @@ -184,13 +187,13 @@ class HopeOfGhirapurCombatDamageWatcher extends Watcher { @Override public void watch(GameEvent event, Game game) { if (event.getType() == EventType.DAMAGED_PLAYER && ((DamagedPlayerEvent) event).isCombatDamage()) { - UUID damagerId = event.getSourceId(); + MageObjectReference damager = new MageObjectReference(event.getSourceId(), game); Set players; - if (combatDamagedPlayers.containsKey(damagerId)) { - players = combatDamagedPlayers.get(damagerId); + if (combatDamagedPlayers.containsKey(damager)) { + players = combatDamagedPlayers.get(damager); } else { players = new HashSet<>(); - combatDamagedPlayers.put(damagerId, players); + combatDamagedPlayers.put(damager, players); } players.add(event.getTargetId()); } @@ -204,9 +207,17 @@ class HopeOfGhirapurCombatDamageWatcher extends Watcher { * @param playerId * @return */ - public boolean playerGotCombatDamage(UUID objectId, UUID playerId) { - if (combatDamagedPlayers.containsKey(objectId)) { - return combatDamagedPlayers.get(objectId).contains(playerId); + public boolean playerGotCombatDamage(UUID objectId, UUID playerId, Game game) { + StackObject stackObject = game.getState().getStack().getStackObject(objectId); + MageObjectReference mor; + if (stackObject != null && stackObject instanceof StackAbility) { + // This is neccessary because the source object was sacrificed as cost and the correct zone change counter for target calid check can only be get from stack + mor = new MageObjectReference(objectId, ((StackAbility) stackObject).getSourceObjectZoneChangeCounter(), game); + } else { + mor = new MageObjectReference(objectId, game); + } + if (combatDamagedPlayers.containsKey(mor)) { + return combatDamagedPlayers.get(mor).contains(playerId); } return false; } diff --git a/Mage.Sets/src/mage/cards/h/HornetNest.java b/Mage.Sets/src/mage/cards/h/HornetNest.java index aaf82d24c9..b8bb917844 100644 --- a/Mage.Sets/src/mage/cards/h/HornetNest.java +++ b/Mage.Sets/src/mage/cards/h/HornetNest.java @@ -60,7 +60,7 @@ public class HornetNest extends CardImpl { // Defender this.addAbility(DefenderAbility.getInstance()); // Whenever Hornet Nest is dealt damage, create that many 1/1 green Insect creature tokens with flying and deathtouch. - this.addAbility(new DealtDamageToSourceTriggeredAbility(Zone.BATTLEFIELD, new HornetNestDealDamageEffect(), false)); + this.addAbility(new DealtDamageToSourceTriggeredAbility(Zone.BATTLEFIELD, new HornetNestDealDamageEffect(), false, false, true)); } public HornetNest(final HornetNest card) { diff --git a/Mage.Sets/src/mage/cards/i/IllusoryAmbusher.java b/Mage.Sets/src/mage/cards/i/IllusoryAmbusher.java index c8f112bddb..e41b9a464f 100644 --- a/Mage.Sets/src/mage/cards/i/IllusoryAmbusher.java +++ b/Mage.Sets/src/mage/cards/i/IllusoryAmbusher.java @@ -49,7 +49,7 @@ import mage.players.Player; public class IllusoryAmbusher extends CardImpl { public IllusoryAmbusher(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{U}"); this.subtype.add(SubType.CAT); this.subtype.add(SubType.ILLUSION); this.power = new MageInt(4); @@ -57,9 +57,9 @@ public class IllusoryAmbusher extends CardImpl { // Flash this.addAbility(FlashAbility.getInstance()); - + // Whenever Illusory Ambusher is dealt damage, draw that many cards. - this.addAbility(new DealtDamageToSourceTriggeredAbility(Zone.BATTLEFIELD, new IllusoryAmbusherDealtDamageEffect(), false)); + this.addAbility(new DealtDamageToSourceTriggeredAbility(Zone.BATTLEFIELD, new IllusoryAmbusherDealtDamageEffect(), false, false, true)); } public IllusoryAmbusher(final IllusoryAmbusher card) { @@ -100,4 +100,4 @@ class IllusoryAmbusherDealtDamageEffect extends OneShotEffect { } return false; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/j/JackalPup.java b/Mage.Sets/src/mage/cards/j/JackalPup.java index 3f9a7ffb6e..f4984ef300 100644 --- a/Mage.Sets/src/mage/cards/j/JackalPup.java +++ b/Mage.Sets/src/mage/cards/j/JackalPup.java @@ -49,14 +49,14 @@ import mage.players.Player; public class JackalPup extends CardImpl { public JackalPup(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{R}"); this.subtype.add(SubType.JACKAL); this.power = new MageInt(2); this.toughness = new MageInt(1); // Whenever Jackal Pup is dealt damage, it deals that much damage to you. - this.addAbility(new DealtDamageToSourceTriggeredAbility(Zone.BATTLEFIELD, new JackalPupEffect(), false)); + this.addAbility(new DealtDamageToSourceTriggeredAbility(Zone.BATTLEFIELD, new JackalPupEffect(), false, false, true)); } diff --git a/Mage.Sets/src/mage/cards/j/JotunOwlKeeper.java b/Mage.Sets/src/mage/cards/j/JotunOwlKeeper.java index 423a5415af..0e47d8117e 100644 --- a/Mage.Sets/src/mage/cards/j/JotunOwlKeeper.java +++ b/Mage.Sets/src/mage/cards/j/JotunOwlKeeper.java @@ -30,6 +30,7 @@ package mage.cards.j; import java.util.UUID; import mage.MageInt; import mage.abilities.common.DiesTriggeredAbility; +import mage.abilities.costs.OrCost; import mage.constants.SubType; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.dynamicvalue.common.CountersSourceCount; @@ -55,7 +56,11 @@ public class JotunOwlKeeper extends CardImpl { this.toughness = new MageInt(3); // Cumulative upkeep {W} or {U} - this.addAbility(new CumulativeUpkeepAbility(new ManaCostsImpl("{W/U}"))); + this.addAbility(new CumulativeUpkeepAbility(new OrCost( + new ManaCostsImpl("{W}"), + new ManaCostsImpl("{U}"), + "{W} or {U}" + ))); // When Jötun Owl Keeper dies, put a 1/1 white Bird creature token with flying onto the battlefield for each age counter on it. this.addAbility(new DiesTriggeredAbility(new CreateTokenEffect(new BirdToken(), new CountersSourceCount(CounterType.AGE)))); diff --git a/Mage.Sets/src/mage/cards/k/KelsinkoRanger.java b/Mage.Sets/src/mage/cards/k/KelsinkoRanger.java new file mode 100644 index 0000000000..3ba4fd3c08 --- /dev/null +++ b/Mage.Sets/src/mage/cards/k/KelsinkoRanger.java @@ -0,0 +1,85 @@ +/* + * 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.cards.k; + +import java.util.UUID; +import mage.MageInt; +import mage.ObjectColor; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author TheElk801 + */ +public class KelsinkoRanger extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("green creature"); + + static { + filter.add(new ColorPredicate(ObjectColor.GREEN)); + } + + public KelsinkoRanger(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}"); + + this.subtype.add(SubType.HUMAN); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // {1}{W}: Target green creature gains first strike until end of turn. + Ability ability = new SimpleActivatedAbility( + Zone.BATTLEFIELD, + new GainAbilityTargetEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn), + new ManaCostsImpl("{1}{W}") + ); + ability.addTarget(new TargetCreaturePermanent(filter)); + this.addAbility(ability); + } + + public KelsinkoRanger(final KelsinkoRanger card) { + super(card); + } + + @Override + public KelsinkoRanger copy() { + return new KelsinkoRanger(this); + } +} diff --git a/Mage.Sets/src/mage/cards/k/KumenasSpeaker.java b/Mage.Sets/src/mage/cards/k/KumenasSpeaker.java index 989a251d08..efc7441604 100644 --- a/Mage.Sets/src/mage/cards/k/KumenasSpeaker.java +++ b/Mage.Sets/src/mage/cards/k/KumenasSpeaker.java @@ -60,6 +60,7 @@ public class KumenasSpeaker extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}"); this.subtype.add(SubType.MERFOLK); + this.subtype.add(SubType.SHAMAN); this.power = new MageInt(1); this.toughness = new MageInt(1); diff --git a/Mage.Sets/src/mage/cards/l/LegacysAllure.java b/Mage.Sets/src/mage/cards/l/LegacysAllure.java index bd96e9f2d7..6d58e0cdfc 100644 --- a/Mage.Sets/src/mage/cards/l/LegacysAllure.java +++ b/Mage.Sets/src/mage/cards/l/LegacysAllure.java @@ -37,15 +37,12 @@ import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.ComparisonType; import mage.constants.Duration; +import mage.constants.TargetAdjustment; import mage.constants.TargetController; import mage.constants.Zone; -import mage.counters.Counter; +import mage.counters.CounterType; import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.mageobject.PowerPredicate; -import mage.game.Game; -import mage.game.permanent.Permanent; import mage.target.common.TargetCreaturePermanent; /** @@ -53,38 +50,24 @@ import mage.target.common.TargetCreaturePermanent; */ public class LegacysAllure extends CardImpl { - private final UUID originalId; + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature with power less than or equal to the number of treasure counters on {this}"); public LegacysAllure(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{U}{U}"); // At the beginning of your upkeep, you may put a treasure counter on Legacy's Allure. - this.addAbility(new BeginningOfUpkeepTriggeredAbility(new AddCountersSourceEffect(new Counter("treasure")), TargetController.YOU, true)); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, + new AddCountersSourceEffect(CounterType.TREASURE.createInstance(), true), TargetController.YOU, true)); // Sacrifice Legacy's Allure: Gain control of target creature with power less than or equal to the number of treasure counters on Legacy's Allure. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new GainControlTargetEffect(Duration.EndOfGame, true), new SacrificeSourceCost()); - ability.addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature with power less than or equal to the number of treasure counters on " + getLogName()))); - originalId = ability.getOriginalId(); + ability.addTarget(new TargetCreaturePermanent(0, 0, filter, false)); + ability.setTargetAdjustment(TargetAdjustment.TREASURE_COUNTER_POWER); this.addAbility(ability); } public LegacysAllure(final LegacysAllure card) { super(card); - this.originalId = card.originalId; - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability.getOriginalId().equals(originalId)) { - Permanent sourcePermanent = game.getPermanent(ability.getSourceId()); - if (sourcePermanent != null) { - int numbCounters = sourcePermanent.getCounters(game).getCount("treasure"); - FilterCreaturePermanent filter = new FilterCreaturePermanent("creature with power less than or equal to the number of treasure counters on " + getLogName()); - filter.add(new PowerPredicate(ComparisonType.FEWER_THAN, numbCounters + 1)); - ability.getTargets().clear(); - ability.getTargets().add(new TargetCreaturePermanent(filter)); - } - } } @Override diff --git a/Mage.Sets/src/mage/cards/l/LilianaDefiantNecromancer.java b/Mage.Sets/src/mage/cards/l/LilianaDefiantNecromancer.java index 0eaca90de6..be62977d53 100644 --- a/Mage.Sets/src/mage/cards/l/LilianaDefiantNecromancer.java +++ b/Mage.Sets/src/mage/cards/l/LilianaDefiantNecromancer.java @@ -75,6 +75,7 @@ public class LilianaDefiantNecromancer extends CardImpl { // +2: Each player discards a card. this.addAbility(new LoyaltyAbility(new DiscardEachPlayerEffect(1, false), 2)); + //TODO: Make ability properly copiable // -X: Return target nonlegendary creature with converted mana cost X from your graveyard to the battlefield. Ability ability = new LoyaltyAbility(new ReturnFromGraveyardToBattlefieldTargetEffect()); ability2Id = ability.getOriginalId(); diff --git a/Mage.Sets/src/mage/cards/l/LimestoneGolem.java b/Mage.Sets/src/mage/cards/l/LimestoneGolem.java new file mode 100644 index 0000000000..9362b44004 --- /dev/null +++ b/Mage.Sets/src/mage/cards/l/LimestoneGolem.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 mage.cards.l; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.DrawCardTargetEffect; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; +import mage.target.TargetPlayer; + +/** + * + * @author TheElk801 + */ +public class LimestoneGolem extends CardImpl { + + public LimestoneGolem(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{6}"); + + this.subtype.add(SubType.GOLEM); + this.power = new MageInt(3); + this.toughness = new MageInt(4); + + // {2}, Sacrifice Limestone Golem: Target player draws a card. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DrawCardTargetEffect(1), new ManaCostsImpl("{2}")); + ability.addCost(new SacrificeSourceCost()); + ability.addTarget(new TargetPlayer()); + this.addAbility(ability); + } + + public LimestoneGolem(final LimestoneGolem card) { + super(card); + } + + @Override + public LimestoneGolem copy() { + return new LimestoneGolem(this); + } +} diff --git a/Mage.Sets/src/mage/cards/l/LinessaZephyrMage.java b/Mage.Sets/src/mage/cards/l/LinessaZephyrMage.java index a3d8e126ca..097b5f3210 100644 --- a/Mage.Sets/src/mage/cards/l/LinessaZephyrMage.java +++ b/Mage.Sets/src/mage/cards/l/LinessaZephyrMage.java @@ -40,22 +40,21 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.ComparisonType; import mage.constants.Outcome; import mage.constants.SuperType; +import mage.constants.TargetAdjustment; import mage.constants.Zone; +import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledPermanent; -import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.CardTypePredicate; -import mage.filter.predicate.mageobject.ConvertedManaCostPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.TargetPlayer; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetControlledPermanent; -import mage.target.common.TargetCreaturePermanent; /** * @@ -63,10 +62,14 @@ import mage.target.common.TargetCreaturePermanent; */ public class LinessaZephyrMage extends CardImpl { - private final UUID originalId; + private static final FilterPermanent filter = new FilterPermanent("creature with converted mana cost X"); + + static { + filter.add(new CardTypePredicate(CardType.CREATURE)); + } public LinessaZephyrMage(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}"); this.addSuperType(SuperType.LEGENDARY); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.WIZARD); @@ -74,12 +77,11 @@ public class LinessaZephyrMage extends CardImpl { this.power = new MageInt(3); this.toughness = new MageInt(3); - //TODO: Make ability properly copiable // {X}{U}{U}, {tap}: Return target creature with converted mana cost X to its owner's hand. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ReturnToHandTargetEffect(), new ManaCostsImpl("{X}{U}{U}")); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent()); - originalId = ability.getOriginalId(); + ability.addTarget(new TargetPermanent(filter)); + ability.setTargetAdjustment(TargetAdjustment.X_CMC_EQUAL_PERM); this.addAbility(ability); // Grandeur - Discard another card named Linessa, Zephyr Mage: Target player returns a creature he or she controls to its owner's hand, then repeats this process for an artifact, an enchantment, and a land. @@ -90,18 +92,6 @@ public class LinessaZephyrMage extends CardImpl { public LinessaZephyrMage(final LinessaZephyrMage card) { super(card); - this.originalId = card.originalId; - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability.getOriginalId().equals(originalId)) { - int xValue = ability.getManaCostsToPay().getX(); - ability.getTargets().clear(); - FilterCreaturePermanent filter = new FilterCreaturePermanent("creature with converted mana cost " + xValue); - filter.add(new ConvertedManaCostPredicate(ComparisonType.EQUAL_TO, xValue)); - ability.getTargets().add(new TargetCreaturePermanent(filter)); - } } @Override diff --git a/Mage.Sets/src/mage/cards/m/MagusOfTheCandelabra.java b/Mage.Sets/src/mage/cards/m/MagusOfTheCandelabra.java index c9a584d835..d1a5c93b32 100644 --- a/Mage.Sets/src/mage/cards/m/MagusOfTheCandelabra.java +++ b/Mage.Sets/src/mage/cards/m/MagusOfTheCandelabra.java @@ -39,48 +39,36 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; +import mage.constants.TargetAdjustment; import mage.constants.Zone; import mage.filter.StaticFilters; -import mage.game.Game; -import mage.target.common.TargetLandPermanent; +import mage.target.TargetPermanent; /** * @author duncant */ public class MagusOfTheCandelabra extends CardImpl { - private final UUID originalId; - public MagusOfTheCandelabra(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}"); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.WIZARD); this.power = new MageInt(1); this.toughness = new MageInt(2); - //TODO: Make ability properly copiable // {X}, {T}: Untap X target lands. Effect effect = new UntapTargetEffect(); effect.setText("untap X target lands"); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl("{X}")); ability.addCost(new TapSourceCost()); - originalId = ability.getOriginalId(); + ability.addTarget(new TargetPermanent(StaticFilters.FILTER_LANDS)); + ability.setTargetAdjustment(TargetAdjustment.X_TARGETS); this.addAbility(ability); } - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability.getOriginalId().equals(originalId)){ - int xValue = ability.getManaCostsToPay().getX(); - ability.getTargets().clear(); - ability.addTarget(new TargetLandPermanent(xValue, xValue, StaticFilters.FILTER_LANDS, false)); - } - } - public MagusOfTheCandelabra(final MagusOfTheCandelabra card) { super(card); - this.originalId = card.originalId; } @Override diff --git a/Mage.Sets/src/mage/cards/m/MinamoSightbender.java b/Mage.Sets/src/mage/cards/m/MinamoSightbender.java index 2b58cb8755..a856679fa7 100644 --- a/Mage.Sets/src/mage/cards/m/MinamoSightbender.java +++ b/Mage.Sets/src/mage/cards/m/MinamoSightbender.java @@ -33,19 +33,17 @@ import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.combat.CantBeBlockedTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.ComparisonType; +import mage.constants.TargetAdjustment; import mage.constants.Zone; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.mageobject.PowerPredicate; -import mage.game.Game; +import mage.filter.FilterPermanent; +import mage.filter.predicate.mageobject.CardTypePredicate; import mage.target.Target; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; /** * @@ -53,48 +51,32 @@ import mage.target.common.TargetCreaturePermanent; */ public class MinamoSightbender extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature with power X or less"); - private final UUID originalId; + private static final FilterPermanent filter = new FilterPermanent("creature with power X or less"); + + static { + filter.add(new CardTypePredicate(CardType.CREATURE)); + } public MinamoSightbender(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}"); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.WIZARD); this.power = new MageInt(1); this.toughness = new MageInt(2); - //TODO: Make ability properly copiable // {X}, {T}: Target creature with power X or less can't be blocked this turn. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CantBeBlockedTargetEffect(), new ManaCostsImpl("{X}")); - Target target = new TargetCreaturePermanent(filter); + Target target = new TargetPermanent(filter); + ability.setTargetAdjustment(TargetAdjustment.X_POWER_LEQ); ability.addTarget(target); ability.addCost(new TapSourceCost()); - originalId = ability.getOriginalId(); this.addAbility(ability); } - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability.getOriginalId().equals(originalId)) { - for (Effect effect : ability.getEffects()) { - if (effect instanceof CantBeBlockedTargetEffect) { - int manaX = ability.getManaCostsToPay().getX(); - ability.getTargets().clear(); - FilterCreaturePermanent newFilter = new FilterCreaturePermanent(new StringBuilder("creature with power ").append(manaX).append(" or less").toString()); - filter.add(new PowerPredicate(ComparisonType.FEWER_THAN, manaX + 1)); - Target target = new TargetCreaturePermanent(newFilter); - ability.addTarget(target); - break; - } - } - } - } - public MinamoSightbender(final MinamoSightbender card) { super(card); - this.originalId = card.originalId; } @Override diff --git a/Mage.Sets/src/mage/cards/m/MishrasHelix.java b/Mage.Sets/src/mage/cards/m/MishrasHelix.java index c8beab689b..8d3446a039 100644 --- a/Mage.Sets/src/mage/cards/m/MishrasHelix.java +++ b/Mage.Sets/src/mage/cards/m/MishrasHelix.java @@ -37,43 +37,31 @@ import mage.abilities.effects.common.TapTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.TargetAdjustment; import mage.constants.Zone; import mage.filter.StaticFilters; -import mage.game.Game; -import mage.target.common.TargetLandPermanent; +import mage.target.TargetPermanent; /** * * @author fireshoes */ public class MishrasHelix extends CardImpl { - - private final UUID originalId; public MishrasHelix(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{5}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{5}"); - //TODO: Make ability properly copiable // {X}, {tap}: Tap X target lands. Effect effect = new TapTargetEffect("X target lands"); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl("{X}")); ability.addCost(new TapSourceCost()); - originalId = ability.getOriginalId(); + ability.addTarget(new TargetPermanent(StaticFilters.FILTER_LANDS)); + ability.setTargetAdjustment(TargetAdjustment.X_TARGETS); this.addAbility(ability); } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability.getOriginalId().equals(originalId)){ - int xValue = ability.getManaCostsToPay().getX(); - ability.getTargets().clear(); - ability.addTarget(new TargetLandPermanent(xValue, xValue, StaticFilters.FILTER_LANDS, false)); - } - } public MishrasHelix(final MishrasHelix card) { super(card); - this.originalId = card.originalId; } @Override diff --git a/Mage.Sets/src/mage/cards/m/MoggManiac.java b/Mage.Sets/src/mage/cards/m/MoggManiac.java index c432792c8d..73423646f3 100644 --- a/Mage.Sets/src/mage/cards/m/MoggManiac.java +++ b/Mage.Sets/src/mage/cards/m/MoggManiac.java @@ -49,13 +49,13 @@ import mage.target.common.TargetOpponent; public class MoggManiac extends CardImpl { public MoggManiac(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}"); this.subtype.add(SubType.GOBLIN); this.power = new MageInt(1); this.toughness = new MageInt(1); // Whenever Mogg Maniac is dealt damage, it deals that much damage to target opponent. - Ability ability = new DealtDamageToSourceTriggeredAbility(Zone.BATTLEFIELD, new MoggManiacDealDamageEffect(), false); + Ability ability = new DealtDamageToSourceTriggeredAbility(Zone.BATTLEFIELD, new MoggManiacDealDamageEffect(), false, false, true); ability.addTarget(new TargetOpponent()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/n/NissaGenesisMage.java b/Mage.Sets/src/mage/cards/n/NissaGenesisMage.java index 47029709e5..f06bd347c3 100644 --- a/Mage.Sets/src/mage/cards/n/NissaGenesisMage.java +++ b/Mage.Sets/src/mage/cards/n/NissaGenesisMage.java @@ -37,8 +37,8 @@ import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Duration; +import mage.constants.SubType; import mage.constants.SuperType; import mage.constants.Zone; import mage.filter.FilterCard; @@ -63,7 +63,7 @@ public class NissaGenesisMage extends CardImpl { this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(5)); //+2: Untap up to two target creatures and up to two target lands. - Ability ability = new LoyaltyAbility(new UntapTargetEffect().setText("Untap up to two target creatures and up to two target lands"), +2); + Ability ability = new LoyaltyAbility(new UntapTargetEffect(false).setText("Untap up to two target creatures and up to two target lands"), +2); ability.addTarget(new TargetCreaturePermanent(0, 2, new FilterCreaturePermanent("target creatures"), false)); ability.addTarget(new TargetLandPermanent(0, 2, new FilterLandPermanent("target land"), false)); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/n/NobleSteeds.java b/Mage.Sets/src/mage/cards/n/NobleSteeds.java new file mode 100644 index 0000000000..c7a748569f --- /dev/null +++ b/Mage.Sets/src/mage/cards/n/NobleSteeds.java @@ -0,0 +1,70 @@ +/* + * 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.cards.n; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Zone; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author TheElk801 + */ +public class NobleSteeds extends CardImpl { + + public NobleSteeds(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}"); + + // {1}{W}: Target creature gains first strike until end of turn. + Ability ability = new SimpleActivatedAbility( + Zone.BATTLEFIELD, + new GainAbilityTargetEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn), + new ManaCostsImpl("{1}{W}") + ); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + public NobleSteeds(final NobleSteeds card) { + super(card); + } + + @Override + public NobleSteeds copy() { + return new NobleSteeds(this); + } +} diff --git a/Mage.Sets/src/mage/cards/o/OldGrowthDryads.java b/Mage.Sets/src/mage/cards/o/OldGrowthDryads.java index 8f3438977c..a0dfc49a7d 100644 --- a/Mage.Sets/src/mage/cards/o/OldGrowthDryads.java +++ b/Mage.Sets/src/mage/cards/o/OldGrowthDryads.java @@ -30,6 +30,7 @@ package mage.cards.o; import java.util.HashSet; import java.util.Set; import java.util.UUID; + import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; @@ -38,10 +39,10 @@ import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Outcome; +import mage.constants.SubType; import mage.constants.Zone; -import mage.filter.common.FilterLandCard; +import mage.filter.common.FilterBasicLandCard; import mage.game.Game; import mage.players.Player; import mage.target.common.TargetCardInLibrary; @@ -94,8 +95,8 @@ class OldGrowthDryadsEffect extends OneShotEffect { Set playersThatSearched = new HashSet<>(1); for (UUID opponentId : game.getOpponents(source.getControllerId())) { Player opponent = game.getPlayer(opponentId); - if (opponent != null && opponent.chooseUse(Outcome.PutCreatureInPlay, "Search your library for a creature card and put it onto the battlefield?", source, game)) { - TargetCardInLibrary target = new TargetCardInLibrary(new FilterLandCard()); + if (opponent != null && opponent.chooseUse(Outcome.PutLandInPlay, "Search your library for a basic land card and put it onto the battlefield tapped?", source, game)) { + TargetCardInLibrary target = new TargetCardInLibrary(new FilterBasicLandCard()); if (opponent.searchLibrary(target, game)) { Card targetCard = opponent.getLibrary().getCard(target.getFirstTarget(), game); if (targetCard != null) { diff --git a/Mage.Sets/src/mage/cards/p/PentarchPaladin.java b/Mage.Sets/src/mage/cards/p/PentarchPaladin.java index 8ed6f885ac..86a28c5eb4 100644 --- a/Mage.Sets/src/mage/cards/p/PentarchPaladin.java +++ b/Mage.Sets/src/mage/cards/p/PentarchPaladin.java @@ -29,7 +29,6 @@ package mage.cards.p; import java.util.UUID; import mage.MageInt; -import mage.ObjectColor; import mage.abilities.Ability; import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.SimpleActivatedAbility; @@ -44,23 +43,21 @@ import mage.constants.SubType; import mage.constants.Outcome; import mage.constants.Zone; import mage.filter.FilterPermanent; -import mage.filter.predicate.mageobject.ColorPredicate; -import mage.game.Game; import mage.target.TargetPermanent; import mage.abilities.effects.common.DestroyTargetEffect; +import mage.constants.TargetAdjustment; /** * * @author jeffwadsworth */ public class PentarchPaladin extends CardImpl { - - private final UUID originalId; + FilterPermanent filter = new FilterPermanent("permanent of the chosen color."); public PentarchPaladin(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}{W}{W}"); - + this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.KNIGHT); this.power = new MageInt(3); @@ -71,36 +68,21 @@ public class PentarchPaladin extends CardImpl { // As Pentarch Paladin enters the battlefield, choose a color. this.addAbility(new AsEntersBattlefieldAbility(new ChooseColorEffect(Outcome.Detriment))); - + // {W}{W}, {tap}: Destroy target permanent of the chosen color. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DestroyTargetEffect(), new ManaCostsImpl("{W}{W}")); ability.addCost(new TapSourceCost()); ability.addTarget(new TargetPermanent(filter)); - originalId = ability.getOriginalId(); + ability.setTargetAdjustment(TargetAdjustment.CHOSEN_COLOR); this.addAbility(ability); - - } - - @Override - public void adjustTargets(Ability ability, Game game) { - ObjectColor color = (ObjectColor) game.getState().getValue(ability.getSourceId() + "_color"); - if (ability.getOriginalId().equals(originalId) - && color != null) { - ability.getTargets().clear(); - FilterPermanent filter = new FilterPermanent("permanent of the chosen color."); - filter.add(new ColorPredicate(color)); - TargetPermanent target = new TargetPermanent(filter); - ability.addTarget(target); - } } public PentarchPaladin(final PentarchPaladin card) { super(card); - this.originalId = card.originalId; } @Override public PentarchPaladin copy() { return new PentarchPaladin(this); } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/p/PhantasmalFiend.java b/Mage.Sets/src/mage/cards/p/PhantasmalFiend.java new file mode 100644 index 0000000000..9accaf657a --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/PhantasmalFiend.java @@ -0,0 +1,71 @@ +/* + * 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.cards.p; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.abilities.effects.common.continuous.SwitchPowerToughnessSourceEffect; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Zone; + +/** + * + * @author TheElk801 + */ +public class PhantasmalFiend extends CardImpl { + + public PhantasmalFiend(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}"); + + this.subtype.add(SubType.ILLUSION); + this.power = new MageInt(1); + this.toughness = new MageInt(5); + + // {B}: Phantasmal Fiend gets +1/-1 until end of turn. + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostSourceEffect(1, -1, Duration.EndOfTurn), new ManaCostsImpl("{B}"))); + + // {1}{U}: Switch Phantasmal Fiend's power and toughness until end of turn. + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new SwitchPowerToughnessSourceEffect(Duration.EndOfTurn), new ManaCostsImpl("{1}{U}"))); + } + + public PhantasmalFiend(final PhantasmalFiend card) { + super(card); + } + + @Override + public PhantasmalFiend copy() { + return new PhantasmalFiend(this); + } +} diff --git a/Mage.Sets/src/mage/cards/p/Plaguebearer.java b/Mage.Sets/src/mage/cards/p/Plaguebearer.java index e308d6b8ee..819b32dce0 100644 --- a/Mage.Sets/src/mage/cards/p/Plaguebearer.java +++ b/Mage.Sets/src/mage/cards/p/Plaguebearer.java @@ -38,14 +38,12 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.ComparisonType; +import mage.constants.TargetAdjustment; import mage.constants.Zone; -import mage.filter.common.FilterCreaturePermanent; +import mage.filter.FilterPermanent; import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; import mage.filter.predicate.mageobject.ColorPredicate; -import mage.filter.predicate.mageobject.ConvertedManaCostPredicate; -import mage.game.Game; -import mage.target.Target; import mage.target.TargetPermanent; /** @@ -54,43 +52,28 @@ import mage.target.TargetPermanent; */ public class Plaguebearer extends CardImpl { - private final UUID originalId; - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nonblack creature"); + private static final FilterPermanent filter = new FilterPermanent("nonblack creature with converted mana cost X"); static { + filter.add(new CardTypePredicate(CardType.CREATURE)); filter.add(Predicates.not(new ColorPredicate(ObjectColor.BLACK))); } public Plaguebearer(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}"); this.subtype.add(SubType.ZOMBIE); this.power = new MageInt(1); this.toughness = new MageInt(1); - //TODO: Make ability properly copiable // {X}{X}{B}: Destroy target nonblack creature with converted mana cost X. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DestroyTargetEffect(), new ManaCostsImpl("{X}{X}{B}")); ability.addTarget(new TargetPermanent(filter)); - originalId = ability.getOriginalId(); + ability.setTargetAdjustment(TargetAdjustment.X_CMC_EQUAL_PERM); this.addAbility(ability); } - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability.getOriginalId().equals(originalId)) { - int xValue = ability.getManaCostsToPay().getX(); - ability.getTargets().clear(); - FilterCreaturePermanent filter = new FilterCreaturePermanent(new StringBuilder("nonblack creature with converted mana cost ").append(xValue).toString()); - filter.add(new ConvertedManaCostPredicate(ComparisonType.EQUAL_TO, xValue)); - filter.add(Predicates.not(new ColorPredicate(ObjectColor.BLACK))); - Target target = new TargetPermanent(filter); - ability.addTarget(target); - } - } - public Plaguebearer(final Plaguebearer card) { super(card); - this.originalId = card.originalId; } @Override diff --git a/Mage.Sets/src/mage/cards/p/PsionicEntity.java b/Mage.Sets/src/mage/cards/p/PsionicEntity.java new file mode 100644 index 0000000000..105de19b4b --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/PsionicEntity.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 mage.cards.p; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.common.DamageSelfEffect; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; +import mage.target.common.TargetCreatureOrPlayer; + +/** + * + * @author TheElk801 + */ +public class PsionicEntity extends CardImpl { + + public PsionicEntity(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{U}"); + + this.subtype.add(SubType.ILLUSION); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // {tap}: Psionic Entity deals 2 damage to target creature or player and 3 damage to itself. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(2), new TapSourceCost()); + ability.addEffect(new DamageSelfEffect(3).setText("and 3 damage to itself")); + ability.addTarget(new TargetCreatureOrPlayer()); + this.addAbility(ability); + } + + public PsionicEntity(final PsionicEntity card) { + super(card); + } + + @Override + public PsionicEntity copy() { + return new PsionicEntity(this); + } +} diff --git a/Mage.Sets/src/mage/cards/p/PsionicSliver.java b/Mage.Sets/src/mage/cards/p/PsionicSliver.java index c3e0b7576d..c5c26851d3 100644 --- a/Mage.Sets/src/mage/cards/p/PsionicSliver.java +++ b/Mage.Sets/src/mage/cards/p/PsionicSliver.java @@ -55,18 +55,24 @@ public class PsionicSliver extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(SubType.SLIVER, "All Sliver creatures"); public PsionicSliver(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{U}"); this.subtype.add(SubType.SLIVER); this.power = new MageInt(2); this.toughness = new MageInt(2); // All Sliver creatures have "{T}: This creature deals 2 damage to target creature or player and 3 damage to itself." - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(2), new TapSourceCost()); - ability.addEffect(new DamageSelfEffect(3)); + Ability ability = new SimpleActivatedAbility( + Zone.BATTLEFIELD, + new DamageTargetEffect(2).setText("This creature deals 2 damage to target creature or player"), + new TapSourceCost() + ); + ability.addEffect(new DamageSelfEffect(3).setText("3 damage to itself.")); ability.addTarget(new TargetCreatureOrPlayer()); - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, - new GainAbilityAllEffect(ability, Duration.WhileOnBattlefield, - filter, "All Sliver creatures have \"{T}: This creature deals 2 damage to target creature or player and 3 damage to itself.\""))); + this.addAbility( + new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAllEffect(ability, Duration.WhileOnBattlefield, filter, + "All Sliver creatures have \"{T}: This creature deals 2 damage to target creature or player and 3 damage to itself.\"") + ) + ); } public PsionicSliver(final PsionicSliver card) { @@ -77,4 +83,4 @@ public class PsionicSliver extends CardImpl { public PsionicSliver copy() { return new PsionicSliver(this); } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/r/Recantation.java b/Mage.Sets/src/mage/cards/r/Recantation.java new file mode 100644 index 0000000000..e2f9cad954 --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/Recantation.java @@ -0,0 +1,80 @@ +/* + * 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.cards.r; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.ReturnToHandTargetEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.TargetAdjustment; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.filter.FilterPermanent; +import mage.target.TargetPermanent; + +/** + * + * @author TheElk801 + */ +public class Recantation extends CardImpl { + + public Recantation(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{U}"); + + // At the beginning of your upkeep, you may put a verse counter on Recantation. + this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, + new AddCountersSourceEffect(CounterType.VERSE.createInstance(), true), TargetController.YOU, true)); + + // {U}, Sacrifice Recantation: Return up to X target permanents to their owners' hands, where X is the number of verse counters on Recantation. + Effect effect = new ReturnToHandTargetEffect(true); + effect.setText("Return up to X target permanents to their owners' hands, where X is the number of verse counters on {this}."); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl("{U}")); + ability.addCost(new SacrificeSourceCost()); + ability.addTarget(new TargetPermanent(0, 0, new FilterPermanent("up to X target permanents, where X is the number of verse counters on {this}."), false)); + ability.setTargetAdjustment(TargetAdjustment.VERSE_COUNTER_TARGETS); + this.addAbility(ability); + } + + public Recantation(final Recantation card) { + super(card); + } + + @Override + public Recantation copy() { + return new Recantation(this); + } +} diff --git a/Mage.Sets/src/mage/cards/r/RumblingCrescendo.java b/Mage.Sets/src/mage/cards/r/RumblingCrescendo.java new file mode 100644 index 0000000000..093b89338a --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/RumblingCrescendo.java @@ -0,0 +1,87 @@ +/* + * 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.cards.r; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.TargetAdjustment; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.filter.FilterPermanent; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.target.TargetPermanent; + +/** + * + * @author TheElk801 + */ +public class RumblingCrescendo extends CardImpl { + + private static final FilterPermanent filter = new FilterPermanent("up to X target lands, where X is the number of verse counters on {this}"); + + static { + filter.add(new CardTypePredicate(CardType.LAND)); + } + + public RumblingCrescendo(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{R}{R}"); + + // At the beginning of your upkeep, you may put a verse counter on Rumbling Crescendo. + this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, + new AddCountersSourceEffect(CounterType.VERSE.createInstance(), true), TargetController.YOU, true)); + + // {R}, Sacrifice Rumbling Crescendo: Destroy up to X target lands, where X is the number of verse counters on Rumbling Crescendo. + Effect effect = new DestroyTargetEffect(true); + effect.setText("Destroy up to X target lands, where X is the number of verse counters on {this}."); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl("{R}")); + ability.addCost(new SacrificeSourceCost()); + ability.addTarget(new TargetPermanent(0, 0, filter, false)); + ability.setTargetAdjustment(TargetAdjustment.VERSE_COUNTER_TARGETS); + this.addAbility(ability); + } + + public RumblingCrescendo(final RumblingCrescendo card) { + super(card); + } + + @Override + public RumblingCrescendo copy() { + return new RumblingCrescendo(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SaberAnts.java b/Mage.Sets/src/mage/cards/s/SaberAnts.java index 012db4794c..76d872ed7e 100644 --- a/Mage.Sets/src/mage/cards/s/SaberAnts.java +++ b/Mage.Sets/src/mage/cards/s/SaberAnts.java @@ -46,18 +46,18 @@ import mage.players.Player; /** * * @author LoneFox - + * */ public class SaberAnts extends CardImpl { public SaberAnts(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}"); this.subtype.add(SubType.INSECT); this.power = new MageInt(2); this.toughness = new MageInt(3); // Whenever Saber Ants is dealt damage, you may create that many 1/1 green Insect creature tokens. - this.addAbility(new DealtDamageToSourceTriggeredAbility(Zone.BATTLEFIELD, new SaberAntsEffect(), true)); + this.addAbility(new DealtDamageToSourceTriggeredAbility(Zone.BATTLEFIELD, new SaberAntsEffect(), true, false, true)); } public SaberAnts(final SaberAnts card) { diff --git a/Mage.Sets/src/mage/cards/s/ScorchingMissile.java b/Mage.Sets/src/mage/cards/s/ScorchingMissile.java new file mode 100644 index 0000000000..ce756796d5 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/ScorchingMissile.java @@ -0,0 +1,66 @@ +/* + * 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.cards.s; + +import java.util.UUID; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.keyword.FlashbackAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.TimingRule; +import mage.target.TargetPlayer; + +/** + * + * @author TheElk801 + */ +public class ScorchingMissile extends CardImpl { + + public ScorchingMissile(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{R}"); + + // Scorching Missile deals 4 damage to target player. + this.getSpellAbility().addEffect(new DamageTargetEffect(4)); + this.getSpellAbility().addTarget(new TargetPlayer()); + + // Flashback {9}{R} + this.addAbility(new FlashbackAbility(new ManaCostsImpl("{9}{R}"), TimingRule.SORCERY)); + + } + + public ScorchingMissile(final ScorchingMissile card) { + super(card); + } + + @Override + public ScorchingMissile copy() { + return new ScorchingMissile(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SerrasLiturgy.java b/Mage.Sets/src/mage/cards/s/SerrasLiturgy.java new file mode 100644 index 0000000000..a0695c7017 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SerrasLiturgy.java @@ -0,0 +1,91 @@ +/* + * 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.cards.s; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.TargetAdjustment; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.filter.FilterPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.target.TargetPermanent; + +/** + * + * @author TheElk801 + */ +public class SerrasLiturgy extends CardImpl { + + private static final FilterPermanent filter = new FilterPermanent("up to X target artifacts and/or enchantments, where X is the number of verse counters on {this}"); + + static { + filter.add(Predicates.or( + new CardTypePredicate(CardType.ARTIFACT), + new CardTypePredicate(CardType.ENCHANTMENT) + )); + } + + public SerrasLiturgy(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}{W}"); + + // At the beginning of your upkeep, you may put a verse counter on Serra's Liturgy. + this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, + new AddCountersSourceEffect(CounterType.VERSE.createInstance(), true), TargetController.YOU, true)); + + // {W}, Sacrifice Serra's Liturgy: Destroy up to X target artifacts and/or enchantments, where X is the number of verse counters on Serra's Liturgy. + Effect effect = new DestroyTargetEffect(true); + effect.setText("Destroy up to X target artifacts and/or enchantments, where X is the number of verse counters on {this}."); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl("{W}")); + ability.addCost(new SacrificeSourceCost()); + ability.addTarget(new TargetPermanent(0, 0, filter, false)); + ability.setTargetAdjustment(TargetAdjustment.VERSE_COUNTER_TARGETS); + this.addAbility(ability); + } + + public SerrasLiturgy(final SerrasLiturgy card) { + super(card); + } + + @Override + public SerrasLiturgy copy() { + return new SerrasLiturgy(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/ShinkaGatekeeper.java b/Mage.Sets/src/mage/cards/s/ShinkaGatekeeper.java index 9b3064b78a..50ce2f8957 100644 --- a/Mage.Sets/src/mage/cards/s/ShinkaGatekeeper.java +++ b/Mage.Sets/src/mage/cards/s/ShinkaGatekeeper.java @@ -48,7 +48,7 @@ import mage.players.Player; public class ShinkaGatekeeper extends CardImpl { public ShinkaGatekeeper(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}"); this.subtype.add(SubType.OGRE); this.subtype.add(SubType.WARRIOR); @@ -56,7 +56,7 @@ public class ShinkaGatekeeper extends CardImpl { this.toughness = new MageInt(2); // Whenever Shinka Gatekeeper is dealt damage, it deals that much damage to you. - this.addAbility(new DealtDamageToSourceTriggeredAbility(Zone.BATTLEFIELD, new ShinkaGatekeeperDealDamageEffect(), false)); + this.addAbility(new DealtDamageToSourceTriggeredAbility(Zone.BATTLEFIELD, new ShinkaGatekeeperDealDamageEffect(), false, false, true)); } public ShinkaGatekeeper(final ShinkaGatekeeper card) { @@ -69,7 +69,6 @@ public class ShinkaGatekeeper extends CardImpl { } } - class ShinkaGatekeeperDealDamageEffect extends OneShotEffect { public ShinkaGatekeeperDealDamageEffect() { diff --git a/Mage.Sets/src/mage/cards/s/SlaughterhouseBouncer.java b/Mage.Sets/src/mage/cards/s/SlaughterhouseBouncer.java new file mode 100644 index 0000000000..56f90ac158 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SlaughterhouseBouncer.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.cards.s; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.DiesTriggeredAbility; +import mage.abilities.condition.common.HellbentCondition; +import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.AbilityWord; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author TheElk801 + */ +public class SlaughterhouseBouncer extends CardImpl { + + public SlaughterhouseBouncer(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{B}"); + + this.subtype.add(SubType.OGRE); + this.subtype.add(SubType.WARRIOR); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Hellbent - When Slaughterhouse Bouncer dies, if you have no cards in hand, target creature gets -3/-3 until end of turn. + Ability ability = new ConditionalTriggeredAbility( + new DiesTriggeredAbility(new BoostTargetEffect(-3, -3, Duration.EndOfTurn)), + HellbentCondition.instance, + "When {this} dies, if you have no cards in hand, target creature gets -3/-3 until end of turn." + ); + ability.setAbilityWord(AbilityWord.HELLBENT); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + public SlaughterhouseBouncer(final SlaughterhouseBouncer card) { + super(card); + } + + @Override + public SlaughterhouseBouncer copy() { + return new SlaughterhouseBouncer(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SwordOfLightAndShadow.java b/Mage.Sets/src/mage/cards/s/SwordOfLightAndShadow.java index 033ee888e5..e96d1af110 100644 --- a/Mage.Sets/src/mage/cards/s/SwordOfLightAndShadow.java +++ b/Mage.Sets/src/mage/cards/s/SwordOfLightAndShadow.java @@ -62,14 +62,16 @@ import mage.target.common.TargetCardInYourGraveyard; public class SwordOfLightAndShadow extends CardImpl { public SwordOfLightAndShadow(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{3}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); this.subtype.add(SubType.EQUIPMENT); // Equipped creature gets +2/+2 and has protection from white and from black. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(2, 2))); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(ProtectionAbility.from(ObjectColor.WHITE, ObjectColor.BLACK), AttachmentType.EQUIPMENT))); // Whenever equipped creature deals combat damage to a player, you gain 3 life and you may return up to one target creature card from your graveyard to your hand. - this.addAbility(new SwordOfLightAndShadowAbility()); + Ability ability = new SwordOfLightAndShadowAbility(); + ability.addTarget(new TargetCardInYourGraveyard(0, 1, new FilterCreatureCard("creature card from your graveyard"))); + this.addAbility(ability); // Equip {2} this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(2))); } @@ -82,22 +84,6 @@ public class SwordOfLightAndShadow extends CardImpl { public SwordOfLightAndShadow copy() { return new SwordOfLightAndShadow(this); } - - @Override - public void adjustTargets(Ability ability, Game game) { - - if (ability instanceof SwordOfLightAndShadowAbility) { - Player controller = game.getPlayer(ability.getControllerId()); - if (controller != null) { - // Target may only be added if possible target exists. Else the gain life effect won't trigger, because there is no valid target for the - // return to hand ability - if (controller.getGraveyard().count(new FilterCreatureCard(), ability.getSourceId(), ability.getControllerId(), game) > 0) { - ability.addTarget(new TargetCardInYourGraveyard(0, 1, new FilterCreatureCard("creature card from your graveyard"))); - } - } - } - - } } class SwordOfLightAndShadowAbility extends TriggeredAbilityImpl { diff --git a/Mage.Sets/src/mage/cards/s/SynodArtificer.java b/Mage.Sets/src/mage/cards/s/SynodArtificer.java index bd0ac7cc02..937336f0a9 100644 --- a/Mage.Sets/src/mage/cards/s/SynodArtificer.java +++ b/Mage.Sets/src/mage/cards/s/SynodArtificer.java @@ -40,11 +40,11 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; +import mage.constants.TargetAdjustment; 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.target.TargetPermanent; /** @@ -52,54 +52,42 @@ import mage.target.TargetPermanent; * @author escplan9 (Derek Monturo - dmontur1 at gmail dot com) */ public class SynodArtificer extends CardImpl { - - private final UUID tapId; - private final UUID untapId; - private static final FilterPermanent filter = new FilterPermanent("Target noncreature artifacts"); - + + private static final FilterPermanent filter = new FilterPermanent("noncreature artifacts"); + static { filter.add(new CardTypePredicate(CardType.ARTIFACT)); filter.add(Predicates.not(new CardTypePredicate(CardType.CREATURE))); } public SynodArtificer(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}"); this.subtype.add(SubType.VEDALKEN); this.subtype.add(SubType.ARTIFICER); this.power = new MageInt(1); this.toughness = new MageInt(2); - //TODO: Make ability properly copiable // {X}, {tap}: Tap X target noncreature artifacts. Effect tapEffect = new TapTargetEffect(); tapEffect.setText("Tap X target noncreature artifacts."); Ability tapAbility = new SimpleActivatedAbility(Zone.BATTLEFIELD, tapEffect, new ManaCostsImpl("{X}")); - tapAbility.addCost(new TapSourceCost()); + tapAbility.addCost(new TapSourceCost()); + tapAbility.setTargetAdjustment(TargetAdjustment.X_TARGETS); + tapAbility.addTarget(new TargetPermanent(filter)); this.addAbility(tapAbility); - + // {X}, {tap}: Untap X target noncreature artifacts. Effect untapEffect = new UntapTargetEffect(); untapEffect.setText("Untap X target noncreature artifacts."); Ability untapAbility = new SimpleActivatedAbility(Zone.BATTLEFIELD, untapEffect, new ManaCostsImpl("{X}")); untapAbility.addCost(new TapSourceCost()); + untapAbility.setTargetAdjustment(TargetAdjustment.X_TARGETS); + untapAbility.addTarget(new TargetPermanent(filter)); this.addAbility(untapAbility); - - tapId = tapAbility.getOriginalId(); - untapId = untapAbility.getOriginalId(); - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability.getOriginalId().equals(tapId) || ability.getOriginalId().equals(untapId)) { - ability.getTargets().clear(); - ability.addTarget(new TargetPermanent(ability.getManaCostsToPay().getX(), filter)); - } } public SynodArtificer(final SynodArtificer card) { super(card); - this.tapId = card.tapId; - this.untapId = card.untapId; } @Override diff --git a/Mage.Sets/src/mage/cards/t/ThrashingMudspawn.java b/Mage.Sets/src/mage/cards/t/ThrashingMudspawn.java new file mode 100644 index 0000000000..2f67e18edd --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/ThrashingMudspawn.java @@ -0,0 +1,106 @@ +/* + * 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.cards.t; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.DealtDamageToSourceTriggeredAbility; +import mage.constants.SubType; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.MorphAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.game.Game; +import mage.players.Player; + +/** + * + * @author TheElk801 + */ +public class ThrashingMudspawn extends CardImpl { + + public ThrashingMudspawn(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}{B}"); + + this.subtype.add(SubType.BEAST); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // Whenever Thrashing Mudspawn is dealt damage, you lose that much life. + Ability ability = new DealtDamageToSourceTriggeredAbility(Zone.BATTLEFIELD, new ThrashingMudspawnEffect(), false); + this.addAbility(ability); + + // Morph {1}{B}{B} + this.addAbility(new MorphAbility(this, new ManaCostsImpl("{1}{B}{B}"))); + + } + + public ThrashingMudspawn(final ThrashingMudspawn card) { + super(card); + } + + @Override + public ThrashingMudspawn copy() { + return new ThrashingMudspawn(this); + } +} + +class ThrashingMudspawnEffect extends OneShotEffect { + + public ThrashingMudspawnEffect() { + super(Outcome.Damage); + this.staticText = "you lose that much life"; + } + + public ThrashingMudspawnEffect(final ThrashingMudspawnEffect effect) { + super(effect); + } + + @Override + public ThrashingMudspawnEffect copy() { + return new ThrashingMudspawnEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + int amount = (Integer) getValue("damage"); + if (amount > 0) { + Player player = game.getPlayer(source.getControllerId()); + if (player != null) { + player.loseLife(amount, game, false); + return true; + } + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/t/TorchSong.java b/Mage.Sets/src/mage/cards/t/TorchSong.java index 2da5523d9b..d6a19c2a46 100644 --- a/Mage.Sets/src/mage/cards/t/TorchSong.java +++ b/Mage.Sets/src/mage/cards/t/TorchSong.java @@ -51,13 +51,18 @@ import mage.target.common.TargetCreatureOrPlayer; public class TorchSong extends CardImpl { public TorchSong(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{R}"); // At the beginning of your upkeep, you may put a verse counter on Torch Song. this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, - new AddCountersSourceEffect(CounterType.VERSE.createInstance(), true), TargetController.YOU, true)); + new AddCountersSourceEffect(CounterType.VERSE.createInstance(), true), TargetController.YOU, true)); + // {2}{R}, Sacrifice Torch Song: Torch Song deals X damage to target creature or player, where X is the number of verse counters on Torch Song. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(new CountersSourceCount(CounterType.VERSE)), new ManaCostsImpl("{2}{R}")); + Ability ability = new SimpleActivatedAbility( + Zone.BATTLEFIELD, + new DamageTargetEffect(new CountersSourceCount(CounterType.VERSE)), + new ManaCostsImpl("{2}{R}") + ); ability.addCost(new SacrificeSourceCost()); ability.addTarget(new TargetCreatureOrPlayer()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/v/Vebulid.java b/Mage.Sets/src/mage/cards/v/Vebulid.java new file mode 100644 index 0000000000..12469a5883 --- /dev/null +++ b/Mage.Sets/src/mage/cards/v/Vebulid.java @@ -0,0 +1,77 @@ +/* + * 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.cards.v; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.AttacksOrBlocksTriggeredAbility; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.EntersBattlefieldAbility; +import mage.abilities.common.delayed.AtTheEndOfCombatDelayedTriggeredAbility; +import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; +import mage.abilities.effects.common.DestroySourceEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.TargetController; +import mage.counters.CounterType; + +/** + * + * @author TheElk801 + */ +public class Vebulid extends CardImpl { + + public Vebulid(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{B}"); + + this.subtype.add(SubType.HORROR); + this.power = new MageInt(0); + this.toughness = new MageInt(0); + + // Vebulid enters the battlefield with a +1/+1 counter on it. + this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance(1)))); + + // At the beginning of your upkeep, you may put a +1/+1 counter on Vebulid. + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance()), TargetController.YOU, true)); + + // When Vebulid attacks or blocks, destroy it at end of combat. + this.addAbility(new AttacksOrBlocksTriggeredAbility(new CreateDelayedTriggeredAbilityEffect(new AtTheEndOfCombatDelayedTriggeredAbility(new DestroySourceEffect())), false)); + } + + public Vebulid(final Vebulid card) { + super(card); + } + + @Override + public Vebulid copy() { + return new Vebulid(this); + } +} diff --git a/Mage.Sets/src/mage/cards/v/VileRequiem.java b/Mage.Sets/src/mage/cards/v/VileRequiem.java index f32b7afec0..4573f230b6 100644 --- a/Mage.Sets/src/mage/cards/v/VileRequiem.java +++ b/Mage.Sets/src/mage/cards/v/VileRequiem.java @@ -40,16 +40,15 @@ import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.TargetAdjustment; import mage.constants.TargetController; import mage.constants.Zone; import mage.counters.CounterType; -import mage.filter.common.FilterCreaturePermanent; +import mage.filter.FilterPermanent; import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; import mage.filter.predicate.mageobject.ColorPredicate; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.target.common.TargetCreaturePermanent; -import mage.util.CardUtil; +import mage.target.TargetPermanent; /** * @@ -57,48 +56,33 @@ import mage.util.CardUtil; */ public class VileRequiem extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("up to X target nonblack creatures, where X is the number of verse counters on {this}"); + private static final FilterPermanent filter = new FilterPermanent("up to X target nonblack creatures, where X is the number of verse counters on {this}"); + static { filter.add(Predicates.not(new ColorPredicate(ObjectColor.BLACK))); + filter.add(new CardTypePredicate(CardType.CREATURE)); } - private final UUID originalId; public VileRequiem(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{B}{B}"); - - this.color.setBlack(true); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{B}{B}"); // At the beginning of your upkeep, you may put a verse counter on Vile Requiem. this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, - new AddCountersSourceEffect(CounterType.VERSE.createInstance(), true ), TargetController.YOU, true)); + new AddCountersSourceEffect(CounterType.VERSE.createInstance(), true), TargetController.YOU, true)); + // {1}{B}, Sacrifice Vile Requiem: Destroy up to X target nonblack creatures, where X is the number of verse counters on Vile Requiem. They can't be regenerated. Effect effect = new DestroyTargetEffect(true); effect.setText("Destroy up to X target nonblack creatures, where X is the number of verse counters on {this}. They can't be regenerated"); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl("{1}{B}")); ability.addCost(new SacrificeSourceCost()); - ability.addTarget(new TargetCreaturePermanent(0,0,filter, false)); + ability.addTarget(new TargetPermanent(0, 0, filter, false)); + ability.setTargetAdjustment(TargetAdjustment.VERSE_COUNTER_TARGETS); this.addAbility(ability); - originalId = ability.getOriginalId(); } - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability.getOriginalId().equals(originalId)) { - Permanent sourcePermanent = game.getPermanent(ability.getSourceId()); - if (sourcePermanent != null) { - int numberCounters = sourcePermanent.getCounters(game).getCount(CounterType.VERSE); - ability.getTargets().clear(); - FilterCreaturePermanent newFilter = filter.copy(); - newFilter.setMessage(new StringBuilder("up to ").append(CardUtil.numberToText(numberCounters)).append(" target nonblack creatures").toString()); - ability.addTarget(new TargetCreaturePermanent(0,numberCounters,newFilter, false)); - } - } - } - public VileRequiem(final VileRequiem card) { super(card); - this.originalId = card.originalId; } @Override diff --git a/Mage.Sets/src/mage/cards/w/WarDance.java b/Mage.Sets/src/mage/cards/w/WarDance.java new file mode 100644 index 0000000000..93a920d3c1 --- /dev/null +++ b/Mage.Sets/src/mage/cards/w/WarDance.java @@ -0,0 +1,82 @@ +/* + * 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.cards.w; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.dynamicvalue.common.CountersSourceCount; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author TheElk801 + */ +public class WarDance extends CardImpl { + + public WarDance(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{G}"); + + // At the beginning of your upkeep, you may put a verse counter on War Dance. + this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, + new AddCountersSourceEffect(CounterType.VERSE.createInstance(), true), TargetController.YOU, true)); + + // Sacrifice War Dance: Target creature gets +X/+X until end of turn, where X is the number of verse counters on War Dance. + Ability ability = new SimpleActivatedAbility( + Zone.BATTLEFIELD, + new BoostTargetEffect( + new CountersSourceCount(CounterType.VERSE), + new CountersSourceCount(CounterType.VERSE), + Duration.EndOfTurn + ), + new SacrificeSourceCost() + ); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + public WarDance(final WarDance card) { + super(card); + } + + @Override + public WarDance copy() { + return new WarDance(this); + } +} diff --git a/Mage.Sets/src/mage/sets/Alliances.java b/Mage.Sets/src/mage/sets/Alliances.java index 36e2192a5f..b143d7f4a4 100644 --- a/Mage.Sets/src/mage/sets/Alliances.java +++ b/Mage.Sets/src/mage/sets/Alliances.java @@ -107,6 +107,8 @@ public class Alliances extends ExpansionSet { cards.add(new SetCardInfo("Lord of Tresserhorn", 193, Rarity.RARE, mage.cards.l.LordOfTresserhorn.class)); cards.add(new SetCardInfo("Mystic Compass", 166, Rarity.UNCOMMON, mage.cards.m.MysticCompass.class)); cards.add(new SetCardInfo("Nature's Wrath", 82, Rarity.RARE, mage.cards.n.NaturesWrath.class)); + cards.add(new SetCardInfo("Noble Steeds", 140, Rarity.COMMON, mage.cards.n.NobleSteeds.class)); + cards.add(new SetCardInfo("Phantasmal Fiend", 20, Rarity.COMMON, mage.cards.p.PhantasmalFiend.class)); cards.add(new SetCardInfo("Phelddagrif", 196, Rarity.RARE, mage.cards.p.Phelddagrif.class)); cards.add(new SetCardInfo("Phyrexian Devourer", 167, Rarity.RARE, mage.cards.p.PhyrexianDevourer.class)); cards.add(new SetCardInfo("Phyrexian War Beast", 169, Rarity.COMMON, PhyrexianWarBeast.class, NON_FULL_USE_VARIOUS)); diff --git a/Mage.Sets/src/mage/sets/Dissension.java b/Mage.Sets/src/mage/sets/Dissension.java index 86ce3a307e..f6e2b683be 100644 --- a/Mage.Sets/src/mage/sets/Dissension.java +++ b/Mage.Sets/src/mage/sets/Dissension.java @@ -178,6 +178,7 @@ public class Dissension extends ExpansionSet { cards.add(new SetCardInfo("Skullmead Cauldron", 167, Rarity.UNCOMMON, mage.cards.s.SkullmeadCauldron.class)); cards.add(new SetCardInfo("Sky Hussar", 131, Rarity.UNCOMMON, mage.cards.s.SkyHussar.class)); cards.add(new SetCardInfo("Skyscribing", 32, Rarity.UNCOMMON, mage.cards.s.Skyscribing.class)); + cards.add(new SetCardInfo("Slaughterhouse Bouncer", 54, Rarity.COMMON, mage.cards.s.SlaughterhouseBouncer.class)); cards.add(new SetCardInfo("Slithering Shade", 55, Rarity.UNCOMMON, mage.cards.s.SlitheringShade.class)); cards.add(new SetCardInfo("Soulsworn Jury", 17, Rarity.COMMON, mage.cards.s.SoulswornJury.class)); cards.add(new SetCardInfo("Spell Snare", 33, Rarity.UNCOMMON, mage.cards.s.SpellSnare.class)); diff --git a/Mage.Sets/src/mage/sets/FourthEdition.java b/Mage.Sets/src/mage/sets/FourthEdition.java index 3f99bab8b0..606b819a45 100644 --- a/Mage.Sets/src/mage/sets/FourthEdition.java +++ b/Mage.Sets/src/mage/sets/FourthEdition.java @@ -294,6 +294,7 @@ public class FourthEdition extends ExpansionSet { cards.add(new SetCardInfo("Pradesh Gypsies", 149, Rarity.COMMON, mage.cards.p.PradeshGypsies.class)); cards.add(new SetCardInfo("Primal Clay", 360, Rarity.RARE, mage.cards.p.PrimalClay.class)); cards.add(new SetCardInfo("Prodigal Sorcerer", 94, Rarity.COMMON, mage.cards.p.ProdigalSorcerer.class)); + cards.add(new SetCardInfo("Psionic Entity", 95, Rarity.RARE, mage.cards.p.PsionicEntity.class)); cards.add(new SetCardInfo("Psychic Venom", 96, Rarity.COMMON, mage.cards.p.PsychicVenom.class)); cards.add(new SetCardInfo("Purelace", 293, Rarity.RARE, mage.cards.p.Purelace.class)); cards.add(new SetCardInfo("Pyrotechnics", 235, Rarity.UNCOMMON, mage.cards.p.Pyrotechnics.class)); diff --git a/Mage.Sets/src/mage/sets/IceAge.java b/Mage.Sets/src/mage/sets/IceAge.java index 8aec080801..c74afc2c8a 100644 --- a/Mage.Sets/src/mage/sets/IceAge.java +++ b/Mage.Sets/src/mage/sets/IceAge.java @@ -179,6 +179,7 @@ public class IceAge extends ExpansionSet { cards.add(new SetCardInfo("Justice", 256, Rarity.UNCOMMON, mage.cards.j.Justice.class)); cards.add(new SetCardInfo("Karplusan Forest", 337, Rarity.RARE, mage.cards.k.KarplusanForest.class)); cards.add(new SetCardInfo("Karplusan Yeti", 197, Rarity.RARE, mage.cards.k.KarplusanYeti.class)); + cards.add(new SetCardInfo("Kelsinko Ranger", 257, Rarity.COMMON, mage.cards.k.KelsinkoRanger.class)); cards.add(new SetCardInfo("Kjeldoran Dead", 25, Rarity.COMMON, mage.cards.k.KjeldoranDead.class)); cards.add(new SetCardInfo("Kjeldoran Frostbeast", 374, Rarity.UNCOMMON, mage.cards.k.KjeldoranFrostbeast.class)); cards.add(new SetCardInfo("Kjeldoran Royal Guard", 262, Rarity.RARE, mage.cards.k.KjeldoranRoyalGuard.class)); diff --git a/Mage.Sets/src/mage/sets/Ixalan.java b/Mage.Sets/src/mage/sets/Ixalan.java index 03a3a24910..3e35230b86 100644 --- a/Mage.Sets/src/mage/sets/Ixalan.java +++ b/Mage.Sets/src/mage/sets/Ixalan.java @@ -46,7 +46,7 @@ public class Ixalan extends ExpansionSet { cards.add(new SetCardInfo("Ashes of the Abhorrent", 2, Rarity.RARE, mage.cards.a.AshesOfTheAbhorrent.class)); cards.add(new SetCardInfo("Atzocan Archer", 176, Rarity.UNCOMMON, mage.cards.a.AtzocanArcher.class)); cards.add(new SetCardInfo("Axis of Mortality", 3, Rarity.MYTHIC, mage.cards.a.AxisOfMortality.class)); - cards.add(new SetCardInfo("Azcanta, The Sunken Ruin", 74, Rarity.RARE, mage.cards.a.AzcantaTheSunkenRuin.class)); + cards.add(new SetCardInfo("Azcanta, the Sunken Ruin", 74, Rarity.RARE, mage.cards.a.AzcantaTheSunkenRuin.class)); cards.add(new SetCardInfo("Belligerent Brontodon", 218, Rarity.UNCOMMON, mage.cards.b.BelligerentBrontodon.class)); cards.add(new SetCardInfo("Bellowing Aegisaur", 4, Rarity.UNCOMMON, mage.cards.b.BellowingAegisaur.class)); cards.add(new SetCardInfo("Bishop of Rebirth", 5, Rarity.RARE, mage.cards.b.BishopOfRebirth.class)); @@ -193,7 +193,7 @@ public class Ixalan extends ExpansionSet { cards.add(new SetCardInfo("New Horizons", 198, Rarity.COMMON, mage.cards.n.NewHorizons.class)); cards.add(new SetCardInfo("Nest Robber", 152, Rarity.COMMON, mage.cards.n.NestRobber.class)); cards.add(new SetCardInfo("Old-Growth Dryads", 199, Rarity.RARE, mage.cards.o.OldGrowthDryads.class)); - cards.add(new SetCardInfo("One with the Wind", 64, Rarity.COMMON, mage.cards.o.OneWithTheWind.class)); + cards.add(new SetCardInfo("One With the Wind", 64, Rarity.COMMON, mage.cards.o.OneWithTheWind.class)); cards.add(new SetCardInfo("Opt", 65, Rarity.COMMON, mage.cards.o.Opt.class)); cards.add(new SetCardInfo("Otepec Huntmaster", 153, Rarity.UNCOMMON, mage.cards.o.OtepecHuntmaster.class)); cards.add(new SetCardInfo("Overflowing Insight", 66, Rarity.MYTHIC, mage.cards.o.OverflowingInsight.class)); diff --git a/Mage.Sets/src/mage/sets/Legends.java b/Mage.Sets/src/mage/sets/Legends.java index dc47bd91f9..b9046f04da 100644 --- a/Mage.Sets/src/mage/sets/Legends.java +++ b/Mage.Sets/src/mage/sets/Legends.java @@ -187,6 +187,7 @@ public class Legends extends ExpansionSet { cards.add(new SetCardInfo("Pradesh Gypsies", 111, Rarity.UNCOMMON, mage.cards.p.PradeshGypsies.class)); cards.add(new SetCardInfo("Presence of the Master", 200, Rarity.UNCOMMON, mage.cards.p.PresenceOfTheMaster.class)); cards.add(new SetCardInfo("Princess Lucrezia", 289, Rarity.UNCOMMON, mage.cards.p.PrincessLucrezia.class)); + cards.add(new SetCardInfo("Psionic Entity", 67, Rarity.RARE, mage.cards.p.PsionicEntity.class)); cards.add(new SetCardInfo("Pyrotechnics", 158, Rarity.COMMON, mage.cards.p.Pyrotechnics.class)); cards.add(new SetCardInfo("Rabid Wombat", 112, Rarity.UNCOMMON, mage.cards.r.RabidWombat.class)); cards.add(new SetCardInfo("Radjan Spirit", 113, Rarity.UNCOMMON, mage.cards.r.RadjanSpirit.class)); diff --git a/Mage.Sets/src/mage/sets/Legions.java b/Mage.Sets/src/mage/sets/Legions.java index 07fb01d460..581d457d92 100644 --- a/Mage.Sets/src/mage/sets/Legions.java +++ b/Mage.Sets/src/mage/sets/Legions.java @@ -64,6 +64,7 @@ public class Legions extends ExpansionSet { cards.add(new SetCardInfo("Berserk Murlodont", 117, Rarity.COMMON, mage.cards.b.BerserkMurlodont.class)); cards.add(new SetCardInfo("Blade Sliver", 88, Rarity.UNCOMMON, mage.cards.b.BladeSliver.class)); cards.add(new SetCardInfo("Blood Celebrant", 61, Rarity.COMMON, mage.cards.b.BloodCelebrant.class)); + cards.add(new SetCardInfo("Bloodstoke Howler", 89, Rarity.COMMON, mage.cards.b.BloodstokeHowler.class)); cards.add(new SetCardInfo("Branchsnap Lorian", 118, Rarity.UNCOMMON, mage.cards.b.BranchsnapLorian.class)); cards.add(new SetCardInfo("Brontotherium", 119, Rarity.UNCOMMON, mage.cards.b.Brontotherium.class)); cards.add(new SetCardInfo("Brood Sliver", 120, Rarity.RARE, mage.cards.b.BroodSliver.class)); diff --git a/Mage.Sets/src/mage/sets/MastersEditionII.java b/Mage.Sets/src/mage/sets/MastersEditionII.java index 71ce4a93ba..a07fbb7d32 100644 --- a/Mage.Sets/src/mage/sets/MastersEditionII.java +++ b/Mage.Sets/src/mage/sets/MastersEditionII.java @@ -184,6 +184,7 @@ public class MastersEditionII extends ExpansionSet { cards.add(new SetCardInfo("Order of the White Shield", 26, Rarity.UNCOMMON, mage.cards.o.OrderOfTheWhiteShield.class)); cards.add(new SetCardInfo("Panic", 145, Rarity.COMMON, mage.cards.p.Panic.class)); cards.add(new SetCardInfo("Personal Tutor", 58, Rarity.UNCOMMON, mage.cards.p.PersonalTutor.class)); + cards.add(new SetCardInfo("Phantasmal Fiend", 108, Rarity.COMMON, mage.cards.p.PhantasmalFiend.class)); cards.add(new SetCardInfo("Phyrexian Devourer", 216, Rarity.UNCOMMON, mage.cards.p.PhyrexianDevourer.class)); cards.add(new SetCardInfo("Pillage", 146, Rarity.UNCOMMON, mage.cards.p.Pillage.class)); cards.add(new SetCardInfo("Portent", 60, Rarity.COMMON, mage.cards.p.Portent.class)); diff --git a/Mage.Sets/src/mage/sets/Mirage.java b/Mage.Sets/src/mage/sets/Mirage.java index d3db209d9c..1942f3783c 100644 --- a/Mage.Sets/src/mage/sets/Mirage.java +++ b/Mage.Sets/src/mage/sets/Mirage.java @@ -154,6 +154,7 @@ public class Mirage extends ExpansionSet { cards.add(new SetCardInfo("Gravebane Zombie", 25, Rarity.COMMON, mage.cards.g.GravebaneZombie.class)); cards.add(new SetCardInfo("Grave Servitude", 24, Rarity.COMMON, mage.cards.g.GraveServitude.class)); cards.add(new SetCardInfo("Grinning Totem", 268, Rarity.RARE, mage.cards.g.GrinningTotem.class)); + cards.add(new SetCardInfo("Hakim, Loreweaver", 68, Rarity.RARE, mage.cards.h.HakimLoreweaver.class)); cards.add(new SetCardInfo("Hall of Gemstone", 119, Rarity.RARE, mage.cards.h.HallOfGemstone.class)); cards.add(new SetCardInfo("Hammer of Bogardan", 181, Rarity.RARE, mage.cards.h.HammerOfBogardan.class)); cards.add(new SetCardInfo("Harbinger of Night", 26, Rarity.RARE, mage.cards.h.HarbingerOfNight.class)); diff --git a/Mage.Sets/src/mage/sets/Odyssey.java b/Mage.Sets/src/mage/sets/Odyssey.java index 70f7add0ba..e35dbac6d4 100644 --- a/Mage.Sets/src/mage/sets/Odyssey.java +++ b/Mage.Sets/src/mage/sets/Odyssey.java @@ -153,6 +153,7 @@ public class Odyssey extends ExpansionSet { cards.add(new SetCardInfo("Earth Rift", 189, Rarity.COMMON, mage.cards.e.EarthRift.class)); cards.add(new SetCardInfo("Elephant Ambush", 240, Rarity.COMMON, mage.cards.e.ElephantAmbush.class)); cards.add(new SetCardInfo("Ember Beast", 190, Rarity.COMMON, mage.cards.e.EmberBeast.class)); + cards.add(new SetCardInfo("Embolden", 22, Rarity.COMMON, mage.cards.e.Embolden.class)); cards.add(new SetCardInfo("Engulfing Flames", 191, Rarity.UNCOMMON, mage.cards.e.EngulfingFlames.class)); cards.add(new SetCardInfo("Entomb", 132, Rarity.RARE, mage.cards.e.Entomb.class)); cards.add(new SetCardInfo("Epicenter", 192, Rarity.RARE, mage.cards.e.Epicenter.class)); @@ -205,6 +206,7 @@ public class Odyssey extends ExpansionSet { cards.add(new SetCardInfo("Leaf Dancer", 249, Rarity.COMMON, mage.cards.l.LeafDancer.class)); cards.add(new SetCardInfo("Lieutenant Kirtar", 29, Rarity.RARE, mage.cards.l.LieutenantKirtar.class)); cards.add(new SetCardInfo("Life Burst", 30, Rarity.COMMON, mage.cards.l.LifeBurst.class)); + cards.add(new SetCardInfo("Limestone Golem", 301, Rarity.UNCOMMON, mage.cards.l.LimestoneGolem.class)); cards.add(new SetCardInfo("Liquid Fire", 201, Rarity.UNCOMMON, mage.cards.l.LiquidFire.class)); cards.add(new SetCardInfo("Lithatog", 289, Rarity.UNCOMMON, mage.cards.l.Lithatog.class)); cards.add(new SetCardInfo("Luminous Guardian", 31, Rarity.UNCOMMON, mage.cards.l.LuminousGuardian.class)); @@ -293,6 +295,7 @@ public class Odyssey extends ExpansionSet { cards.add(new SetCardInfo("Sandstone Deadfall", 307, Rarity.UNCOMMON, mage.cards.s.SandstoneDeadfall.class)); cards.add(new SetCardInfo("Sarcatog", 293, Rarity.UNCOMMON, mage.cards.s.Sarcatog.class)); cards.add(new SetCardInfo("Savage Firecat", 218, Rarity.RARE, mage.cards.s.SavageFirecat.class)); + cards.add(new SetCardInfo("Scorching Missile", 219, Rarity.COMMON, mage.cards.s.ScorchingMissile.class)); cards.add(new SetCardInfo("Screams of the Damned", 160, Rarity.UNCOMMON, mage.cards.s.ScreamsOfTheDamned.class)); cards.add(new SetCardInfo("Scrivener", 100, Rarity.COMMON, mage.cards.s.Scrivener.class)); cards.add(new SetCardInfo("Seafloor Debris", 325, Rarity.COMMON, mage.cards.s.SeafloorDebris.class)); diff --git a/Mage.Sets/src/mage/sets/Onslaught.java b/Mage.Sets/src/mage/sets/Onslaught.java index 3d1aa9bb97..74f6caac5e 100644 --- a/Mage.Sets/src/mage/sets/Onslaught.java +++ b/Mage.Sets/src/mage/sets/Onslaught.java @@ -294,6 +294,7 @@ public class Onslaught extends ExpansionSet { cards.add(new SetCardInfo("Taunting Elf", 290, Rarity.COMMON, mage.cards.t.TauntingElf.class)); cards.add(new SetCardInfo("Tempting Wurm", 291, Rarity.RARE, mage.cards.t.TemptingWurm.class)); cards.add(new SetCardInfo("Tephraderm", 239, Rarity.RARE, mage.cards.t.Tephraderm.class)); + cards.add(new SetCardInfo("Thrashing Mudspawn", 177, Rarity.UNCOMMON, mage.cards.t.ThrashingMudspawn.class)); cards.add(new SetCardInfo("Threaten", 241, Rarity.UNCOMMON, mage.cards.t.Threaten.class)); cards.add(new SetCardInfo("Thunder of Hooves", 242, Rarity.UNCOMMON, mage.cards.t.ThunderOfHooves.class)); cards.add(new SetCardInfo("Towering Baloth", 292, Rarity.UNCOMMON, mage.cards.t.ToweringBaloth.class)); diff --git a/Mage.Sets/src/mage/sets/Prophecy.java b/Mage.Sets/src/mage/sets/Prophecy.java index d9043b28ad..eeb8d46fea 100644 --- a/Mage.Sets/src/mage/sets/Prophecy.java +++ b/Mage.Sets/src/mage/sets/Prophecy.java @@ -82,6 +82,7 @@ public class Prophecy extends ExpansionSet { cards.add(new SetCardInfo("Devastate", 87, Rarity.COMMON, mage.cards.d.Devastate.class)); cards.add(new SetCardInfo("Diving Griffin", 6, Rarity.COMMON, mage.cards.d.DivingGriffin.class)); cards.add(new SetCardInfo("Dual Nature", 112, Rarity.RARE, mage.cards.d.DualNature.class)); + cards.add(new SetCardInfo("Elephant Resurgence", 113, Rarity.RARE, mage.cards.e.ElephantResurgence.class)); cards.add(new SetCardInfo("Entangler", 7, Rarity.UNCOMMON, mage.cards.e.Entangler.class)); cards.add(new SetCardInfo("Excavation", 33, Rarity.UNCOMMON, mage.cards.e.Excavation.class)); cards.add(new SetCardInfo("Fault Riders", 88, Rarity.COMMON, mage.cards.f.FaultRiders.class)); diff --git a/Mage.Sets/src/mage/sets/UrzasSaga.java b/Mage.Sets/src/mage/sets/UrzasSaga.java index e883a0b76b..ab6c53b608 100644 --- a/Mage.Sets/src/mage/sets/UrzasSaga.java +++ b/Mage.Sets/src/mage/sets/UrzasSaga.java @@ -261,6 +261,7 @@ public class UrzasSaga extends ExpansionSet { cards.add(new SetCardInfo("Rain of Salt", 206, Rarity.UNCOMMON, mage.cards.r.RainOfSalt.class)); cards.add(new SetCardInfo("Ravenous Skirge", 152, Rarity.COMMON, mage.cards.r.RavenousSkirge.class)); cards.add(new SetCardInfo("Raze", 207, Rarity.COMMON, mage.cards.r.Raze.class)); + cards.add(new SetCardInfo("Recantation", 91, Rarity.RARE, mage.cards.r.Recantation.class)); cards.add(new SetCardInfo("Redeem", 33, Rarity.UNCOMMON, mage.cards.r.Redeem.class)); cards.add(new SetCardInfo("Reflexes", 208, Rarity.COMMON, mage.cards.r.Reflexes.class)); cards.add(new SetCardInfo("Rejuvenate", 271, Rarity.COMMON, mage.cards.r.Rejuvenate.class)); @@ -270,6 +271,7 @@ public class UrzasSaga extends ExpansionSet { cards.add(new SetCardInfo("Rescind", 92, Rarity.COMMON, mage.cards.r.Rescind.class)); cards.add(new SetCardInfo("Retaliation", 272, Rarity.UNCOMMON, mage.cards.r.Retaliation.class)); cards.add(new SetCardInfo("Rewind", 93, Rarity.COMMON, mage.cards.r.Rewind.class)); + cards.add(new SetCardInfo("Rumbling Crescendo", 210, Rarity.RARE, mage.cards.r.RumblingCrescendo.class)); cards.add(new SetCardInfo("Rune of Protection: Artifacts", 35, Rarity.UNCOMMON, mage.cards.r.RuneOfProtectionArtifacts.class)); cards.add(new SetCardInfo("Rune of Protection: Black", 36, Rarity.COMMON, mage.cards.r.RuneOfProtectionBlack.class)); cards.add(new SetCardInfo("Rune of Protection: Blue", 37, Rarity.COMMON, mage.cards.r.RuneOfProtectionBlue.class)); @@ -288,6 +290,7 @@ public class UrzasSaga extends ExpansionSet { cards.add(new SetCardInfo("Seasoned Marshal", 44, Rarity.UNCOMMON, mage.cards.s.SeasonedMarshal.class)); cards.add(new SetCardInfo("Serra Avatar", 45, Rarity.RARE, mage.cards.s.SerraAvatar.class)); cards.add(new SetCardInfo("Serra's Embrace", 47, Rarity.UNCOMMON, mage.cards.s.SerrasEmbrace.class)); + cards.add(new SetCardInfo("Serra's Liturgy", 49, Rarity.RARE, mage.cards.s.SerrasLiturgy.class)); cards.add(new SetCardInfo("Serra's Sanctum", 325, Rarity.RARE, mage.cards.s.SerrasSanctum.class)); cards.add(new SetCardInfo("Serra Zealot", 46, Rarity.COMMON, mage.cards.s.SerraZealot.class)); cards.add(new SetCardInfo("Shimmering Barrier", 50, Rarity.UNCOMMON, mage.cards.s.ShimmeringBarrier.class)); @@ -338,6 +341,7 @@ public class UrzasSaga extends ExpansionSet { cards.add(new SetCardInfo("Unworthy Dead", 163, Rarity.COMMON, mage.cards.u.UnworthyDead.class)); cards.add(new SetCardInfo("Urza's Armor", 313, Rarity.UNCOMMON, mage.cards.u.UrzasArmor.class)); cards.add(new SetCardInfo("Vampiric Embrace", 164, Rarity.UNCOMMON, mage.cards.v.VampiricEmbrace.class)); + cards.add(new SetCardInfo("Vebulid", 165, Rarity.RARE, mage.cards.v.Vebulid.class)); cards.add(new SetCardInfo("Vernal Bloom", 281, Rarity.RARE, mage.cards.v.VernalBloom.class)); cards.add(new SetCardInfo("Viashino Outrider", 223, Rarity.COMMON, mage.cards.v.ViashinoOutrider.class)); cards.add(new SetCardInfo("Viashino Runner", 224, Rarity.COMMON, mage.cards.v.ViashinoRunner.class)); @@ -349,6 +353,7 @@ public class UrzasSaga extends ExpansionSet { cards.add(new SetCardInfo("Voice of Law", 55, Rarity.UNCOMMON, mage.cards.v.VoiceOfLaw.class)); cards.add(new SetCardInfo("Voltaic Key", 314, Rarity.UNCOMMON, mage.cards.v.VoltaicKey.class)); cards.add(new SetCardInfo("Vug Lizard", 227, Rarity.UNCOMMON, mage.cards.v.VugLizard.class)); + cards.add(new SetCardInfo("War Dance", 282, Rarity.UNCOMMON, mage.cards.w.WarDance.class)); cards.add(new SetCardInfo("Wall of Junk", 315, Rarity.UNCOMMON, mage.cards.w.WallOfJunk.class)); cards.add(new SetCardInfo("Western Paladin", 168, Rarity.RARE, mage.cards.w.WesternPaladin.class)); cards.add(new SetCardInfo("Whetstone", 316, Rarity.RARE, mage.cards.w.Whetstone.class)); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/aer/HopeOfGhirapurTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/aer/HopeOfGhirapurTest.java index b0340abb5b..df838afba5 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/single/aer/HopeOfGhirapurTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/aer/HopeOfGhirapurTest.java @@ -35,16 +35,19 @@ public class HopeOfGhirapurTest extends CardTestPlayerBase { // from the battlefield and returned back. @Test public void testWhenHopeOfGhirapurWasRemovedAndReturnedBack() { + // Flying + // Sacrifice Hope of Ghirapur: Until your next turn, target player who was dealt combat damage by Hope of Ghirapur this turn can't cast noncreature spells. addCard(Zone.BATTLEFIELD, playerA, "Hope of Ghirapur"); addCard(Zone.BATTLEFIELD, playerA, "Plains", 1); + // Exile target creature you control, then return that card to the battlefield under your control. addCard(Zone.HAND, playerA, "Cloudshift"); addCard(Zone.BATTLEFIELD, playerB, "Mountain", 1); addCard(Zone.HAND, playerB, "Shock"); attack(1, playerA, "Hope of Ghirapur"); - castSpell(1, PhaseStep.END_COMBAT, playerA, "Cloudshift", "Hope of Ghirapur"); - activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Sacrifice", playerB); + castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Cloudshift", "Hope of Ghirapur"); + activateAbility(1, PhaseStep.END_TURN, playerA, "Sacrifice", playerB); castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Shock", playerA); diff --git a/Mage/src/main/java/mage/abilities/AbilitiesImpl.java b/Mage/src/main/java/mage/abilities/AbilitiesImpl.java index 9f2fba4438..7a1dfba19d 100644 --- a/Mage/src/main/java/mage/abilities/AbilitiesImpl.java +++ b/Mage/src/main/java/mage/abilities/AbilitiesImpl.java @@ -27,6 +27,8 @@ */ package mage.abilities; +import java.util.*; +import java.util.stream.Collectors; import mage.abilities.common.ZoneChangeTriggeredAbility; import mage.abilities.costs.Cost; import mage.abilities.keyword.ProtectionAbility; @@ -37,9 +39,6 @@ import mage.game.Game; import mage.util.ThreadLocalStringBuilder; import org.apache.log4j.Logger; -import java.util.*; -import java.util.stream.Collectors; - /** * @param * @author BetaSteward_at_googlemail.com @@ -164,7 +163,6 @@ public class AbilitiesImpl extends ArrayList implements Ab .filter(ability -> ability.getZone().match(zone)) .collect(Collectors.toCollection(AbilitiesImpl::new)); - } @Override @@ -241,7 +239,7 @@ public class AbilitiesImpl extends ArrayList implements Ab @Override public boolean contains(T ability) { - for (Iterator iterator = this.iterator(); iterator.hasNext(); ) { // simple loop can cause java.util.ConcurrentModificationException + for (Iterator iterator = this.iterator(); iterator.hasNext();) { // simple loop can cause java.util.ConcurrentModificationException T test = iterator.next(); // Checking also by getRule() without other restrictions is a problem when a triggered ability will be copied to a permanent that had the same ability // already before the copy. Because then it keeps the triggered ability twice and it triggers twice. @@ -280,7 +278,7 @@ public class AbilitiesImpl extends ArrayList implements Ab @Override public boolean containsKey(UUID abilityId) { - return stream().anyMatch(ability -> ability.getId().equals(abilityId)); + return stream().anyMatch(ability -> abilityId.equals(ability.getId())); } @Override @@ -295,7 +293,7 @@ public class AbilitiesImpl extends ArrayList implements Ab @Override public int getOutcomeTotal() { return stream().mapToInt(ability -> ability.getEffects().getOutcomeTotal()).sum(); - } + } @Override public String getValue() { diff --git a/Mage/src/main/java/mage/abilities/Ability.java b/Mage/src/main/java/mage/abilities/Ability.java index fcc0a5db82..d6baff95d4 100644 --- a/Mage/src/main/java/mage/abilities/Ability.java +++ b/Mage/src/main/java/mage/abilities/Ability.java @@ -40,6 +40,7 @@ import mage.abilities.effects.Effects; import mage.constants.AbilityType; import mage.constants.AbilityWord; import mage.constants.EffectType; +import mage.constants.TargetAdjustment; import mage.constants.Zone; import mage.game.Controllable; import mage.game.Game; @@ -539,4 +540,8 @@ public interface Ability extends Controllable, Serializable { void setCanFizzle(boolean canFizzle); boolean canFizzle(); + + void setTargetAdjustment(TargetAdjustment targetAdjustment); + + TargetAdjustment getTargetAdjustment(); } diff --git a/Mage/src/main/java/mage/abilities/AbilityImpl.java b/Mage/src/main/java/mage/abilities/AbilityImpl.java index e814b181f0..3fc2020dd7 100644 --- a/Mage/src/main/java/mage/abilities/AbilityImpl.java +++ b/Mage/src/main/java/mage/abilities/AbilityImpl.java @@ -99,6 +99,7 @@ public abstract class AbilityImpl implements Ability { protected List watchers = null; protected List subAbilities = null; protected boolean canFizzle = true; + protected TargetAdjustment targetAdjustment = TargetAdjustment.NONE; public AbilityImpl(AbilityType abilityType, Zone zone) { this.id = UUID.randomUUID(); @@ -147,6 +148,7 @@ public abstract class AbilityImpl implements Ability { this.sourceObject = ability.sourceObject; this.sourceObjectZoneChangeCounter = ability.sourceObjectZoneChangeCounter; this.canFizzle = ability.canFizzle; + this.targetAdjustment = ability.targetAdjustment; } @Override @@ -1233,4 +1235,13 @@ public abstract class AbilityImpl implements Ability { this.canFizzle = canFizzle; } + @Override + public void setTargetAdjustment(TargetAdjustment targetAdjustment) { + this.targetAdjustment = targetAdjustment; + } + + @Override + public TargetAdjustment getTargetAdjustment() { + return targetAdjustment; + } } diff --git a/Mage/src/main/java/mage/abilities/common/DealtDamageToSourceTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/DealtDamageToSourceTriggeredAbility.java index a43abd737a..59c5a26c94 100644 --- a/Mage/src/main/java/mage/abilities/common/DealtDamageToSourceTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/DealtDamageToSourceTriggeredAbility.java @@ -31,6 +31,7 @@ import mage.constants.Zone; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.Effect; import mage.game.Game; +import mage.game.events.DamagedCreatureEvent; import mage.game.events.GameEvent; /** @@ -39,20 +40,30 @@ import mage.game.events.GameEvent; */ public class DealtDamageToSourceTriggeredAbility extends TriggeredAbilityImpl { - private boolean enrage; + private final boolean enrage; + private final boolean useValue; + private boolean usedForCombatDamageStep; public DealtDamageToSourceTriggeredAbility(Zone zone, Effect effect, boolean optional) { this(zone, effect, optional, false); } public DealtDamageToSourceTriggeredAbility(Zone zone, Effect effect, boolean optional, boolean enrage) { + this(zone, effect, optional, enrage, false); + } + + public DealtDamageToSourceTriggeredAbility(Zone zone, Effect effect, boolean optional, boolean enrage, boolean useValue) { super(zone, effect, optional); this.enrage = enrage; + this.useValue = useValue; + this.usedForCombatDamageStep = false; } public DealtDamageToSourceTriggeredAbility(final DealtDamageToSourceTriggeredAbility ability) { super(ability); this.enrage = ability.enrage; + this.useValue = ability.useValue; + this.usedForCombatDamageStep = ability.usedForCombatDamageStep; } @Override @@ -62,16 +73,32 @@ public class DealtDamageToSourceTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.DAMAGED_CREATURE; + return event.getType() == GameEvent.EventType.DAMAGED_CREATURE || event.getType() == GameEvent.EventType.COMBAT_DAMAGE_STEP_POST; } @Override public boolean checkTrigger(GameEvent event, Game game) { - if (event.getTargetId().equals(getSourceId())) { - for (Effect effect : this.getEffects()) { - effect.setValue("damage", event.getAmount()); + if (event.getType() == GameEvent.EventType.DAMAGED_CREATURE && event.getTargetId().equals(getSourceId())) { + if (useValue) { +// TODO: this ability should only trigger once for multiple creatures dealing combat damage. +// If the damaged creature uses the amount (e.g. Boros Reckoner), this will still trigger separately instead of all at once + for (Effect effect : this.getEffects()) { + effect.setValue("damage", event.getAmount()); + } + return true; + } else { + if (((DamagedCreatureEvent) event).isCombatDamage()) { + if (!usedForCombatDamageStep) { + usedForCombatDamageStep = true; + return true; + } + } else { + return true; + } } - return true; + } + if (event.getType() == GameEvent.EventType.COMBAT_DAMAGE_STEP_POST) { + usedForCombatDamageStep = false; } return false; } diff --git a/Mage/src/main/java/mage/abilities/decorator/ConditionalActivatedAbility.java b/Mage/src/main/java/mage/abilities/decorator/ConditionalActivatedAbility.java index 86186e4b01..5f6cc15444 100644 --- a/Mage/src/main/java/mage/abilities/decorator/ConditionalActivatedAbility.java +++ b/Mage/src/main/java/mage/abilities/decorator/ConditionalActivatedAbility.java @@ -71,6 +71,6 @@ public class ConditionalActivatedAbility extends ActivatedAbilityImpl { if (ruleText != null && !ruleText.isEmpty()) { return ruleText; } - return super.getRule() + " Activate this ability only " + condition.toString(); + return super.getRule() + " Activate this ability only " + condition.toString() + "."; } } diff --git a/Mage/src/main/java/mage/cards/CardImpl.java b/Mage/src/main/java/mage/cards/CardImpl.java index 2215ea496a..0e045b2153 100644 --- a/Mage/src/main/java/mage/cards/CardImpl.java +++ b/Mage/src/main/java/mage/cards/CardImpl.java @@ -37,17 +37,32 @@ import mage.MageObjectImpl; import mage.Mana; import mage.ObjectColor; import mage.abilities.*; +import mage.abilities.effects.common.NameACardEffect; import mage.abilities.mana.ActivatedManaAbilityImpl; import mage.cards.repository.PluginClassloaderRegistery; import mage.constants.*; import mage.counters.Counter; +import mage.counters.CounterType; import mage.counters.Counters; +import mage.filter.FilterCard; +import mage.filter.FilterPermanent; +import mage.filter.FilterSpell; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.ColorPredicate; +import mage.filter.predicate.mageobject.ConvertedManaCostPredicate; +import mage.filter.predicate.mageobject.NamePredicate; +import mage.filter.predicate.mageobject.PowerPredicate; import mage.game.*; import mage.game.events.GameEvent; import mage.game.events.ZoneChangeEvent; import mage.game.permanent.Permanent; import mage.game.stack.Spell; import mage.game.stack.StackObject; +import mage.target.TargetCard; +import mage.target.TargetPermanent; +import mage.target.TargetSpell; +import mage.target.common.TargetCardInOpponentsGraveyard; +import mage.target.common.TargetCreaturePermanent; import mage.util.GameLog; import mage.util.SubTypeList; import mage.watchers.Watcher; @@ -317,6 +332,94 @@ public abstract class CardImpl extends MageObjectImpl implements Card { return spellAbility; } +// @Override +// public void adjustCosts(Ability ability, Game game) { +// } + @Override + public void adjustTargets(Ability ability, Game game) { + int xValue; + TargetPermanent oldTargetPermanent; + FilterPermanent permanentFilter; + int minTargets; + int maxTargets; + switch (ability.getTargetAdjustment()) { + case NONE: + break; + case X_CMC_EQUAL_PERM: + xValue = ability.getManaCostsToPay().getX(); + oldTargetPermanent = (TargetPermanent) ability.getTargets().get(0); + minTargets = oldTargetPermanent.getMinNumberOfTargets(); + maxTargets = oldTargetPermanent.getMaxNumberOfTargets(); + permanentFilter = oldTargetPermanent.getFilter().copy(); + permanentFilter.add(new ConvertedManaCostPredicate(ComparisonType.EQUAL_TO, xValue)); + ability.getTargets().clear(); + ability.getTargets().add(new TargetPermanent(minTargets, maxTargets, permanentFilter, false)); + break; + case X_TARGETS: + xValue = ability.getManaCostsToPay().getX(); + permanentFilter = ((TargetPermanent) ability.getTargets().get(0)).getFilter(); + ability.getTargets().clear(); + ability.addTarget(new TargetPermanent(xValue, permanentFilter)); + break; + case X_POWER_LEQ:// Minamo Sightbender only + xValue = ability.getManaCostsToPay().getX(); + oldTargetPermanent = (TargetPermanent) ability.getTargets().get(0); + minTargets = oldTargetPermanent.getMinNumberOfTargets(); + maxTargets = oldTargetPermanent.getMaxNumberOfTargets(); + permanentFilter = oldTargetPermanent.getFilter().copy(); + permanentFilter.add(new PowerPredicate(ComparisonType.FEWER_THAN, xValue + 1)); + ability.getTargets().clear(); + ability.getTargets().add(new TargetPermanent(minTargets, maxTargets, permanentFilter, false)); + break; + case VERSE_COUNTER_TARGETS: + Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(ability.getSourceId()); + if (sourcePermanent != null) { + xValue = sourcePermanent.getCounters(game).getCount(CounterType.VERSE); + permanentFilter = ((TargetPermanent) ability.getTargets().get(0)).getFilter(); + ability.getTargets().clear(); + ability.addTarget(new TargetPermanent(0, xValue, permanentFilter, false)); + } + break; + case X_CMC_EQUAL_GY_CARD: //Geth, Lord of the Vault only + xValue = ability.getManaCostsToPay().getX(); + TargetCard oldTarget = (TargetCard) ability.getTargets().get(0); + FilterCard filterCard = oldTarget.getFilter().copy(); + filterCard.add(new ConvertedManaCostPredicate(ComparisonType.EQUAL_TO, xValue)); + ability.getTargets().clear(); + ability.getTargets().add(new TargetCardInOpponentsGraveyard(filterCard)); + break; + case CHOSEN_NAME: //Declaration of Naught only + ability.getTargets().clear(); + FilterSpell filterSpell = new FilterSpell("spell with the chosen name"); + filterSpell.add(new NamePredicate((String) game.getState().getValue(ability.getSourceId().toString() + NameACardEffect.INFO_KEY))); + TargetSpell target = new TargetSpell(1, filterSpell); + ability.addTarget(target); + break; + case CHOSEN_COLOR: //Pentarch Paladin only + ObjectColor chosenColor = (ObjectColor) game.getState().getValue(ability.getSourceId() + "_color"); + ability.getTargets().clear(); + FilterPermanent filter = new FilterPermanent("permanent of the chosen color."); + if (chosenColor != null) { + filter.add(new ColorPredicate(chosenColor)); + } else { + filter.add(new ConvertedManaCostPredicate(ComparisonType.FEWER_THAN, -5));// Pretty sure this is always false + } + oldTargetPermanent = new TargetPermanent(filter); + ability.addTarget(oldTargetPermanent); + break; + case TREASURE_COUNTER_POWER: //Legacy's Allure only + sourcePermanent = game.getPermanentOrLKIBattlefield(ability.getSourceId()); + if (sourcePermanent != null) { + xValue = sourcePermanent.getCounters(game).getCount(CounterType.TREASURE); + FilterCreaturePermanent filter2 = new FilterCreaturePermanent("creature with power less than or equal to the number of treasure counters on {this}"); + filter2.add(new PowerPredicate(ComparisonType.FEWER_THAN, xValue + 1)); + ability.getTargets().clear(); + ability.getTargets().add(new TargetCreaturePermanent(filter2)); + } + break; + } + } + @Override public void setOwnerId(UUID ownerId) { this.ownerId = ownerId; diff --git a/Mage/src/main/java/mage/cards/repository/CardRepository.java b/Mage/src/main/java/mage/cards/repository/CardRepository.java index 87239f4c12..c8c3245cfe 100644 --- a/Mage/src/main/java/mage/cards/repository/CardRepository.java +++ b/Mage/src/main/java/mage/cards/repository/CardRepository.java @@ -58,7 +58,7 @@ public enum CardRepository { // raise this if db structure was changed private static final long CARD_DB_VERSION = 51; // raise this if new cards were added to the server - private static final long CARD_CONTENT_VERSION = 92; + private static final long CARD_CONTENT_VERSION = 93; private Dao cardDao; private Set classNames; diff --git a/Mage/src/main/java/mage/choices/ChoiceColorOrArtifact.java b/Mage/src/main/java/mage/choices/ChoiceColorOrArtifact.java index 5cef5dd467..eb4f52699d 100644 --- a/Mage/src/main/java/mage/choices/ChoiceColorOrArtifact.java +++ b/Mage/src/main/java/mage/choices/ChoiceColorOrArtifact.java @@ -1,6 +1,7 @@ package mage.choices; public class ChoiceColorOrArtifact extends ChoiceColor { + public ChoiceColorOrArtifact() { this.choices.add("Artifacts"); this.message = "Choose protection from"; @@ -16,6 +17,6 @@ public class ChoiceColorOrArtifact extends ChoiceColor { } public boolean isArtifactSelected() { - return choice.equals("Artifacts"); + return "Artifacts".equals(choice); } } diff --git a/Mage/src/main/java/mage/constants/TargetAdjustment.java b/Mage/src/main/java/mage/constants/TargetAdjustment.java new file mode 100644 index 0000000000..0eb07153af --- /dev/null +++ b/Mage/src/main/java/mage/constants/TargetAdjustment.java @@ -0,0 +1,16 @@ +package mage.constants; + +/** + * + * @author TheElk801 + */ +public enum TargetAdjustment { + NONE, + X_TARGETS, + X_CMC_EQUAL_PERM, + X_CMC_EQUAL_GY_CARD, + X_POWER_LEQ, CHOSEN_NAME, + CHOSEN_COLOR, + VERSE_COUNTER_TARGETS, + TREASURE_COUNTER_POWER +} diff --git a/Mage/src/main/java/mage/counters/CounterType.java b/Mage/src/main/java/mage/counters/CounterType.java index cc7ff45b3e..d4b4464157 100644 --- a/Mage/src/main/java/mage/counters/CounterType.java +++ b/Mage/src/main/java/mage/counters/CounterType.java @@ -122,6 +122,7 @@ public enum CounterType { TIME("time"), TOWER("tower"), TRAP("trap"), + TREASURE("treasure"), UNITY("unity"), VELOCITY("velocity"), VERSE("verse"), diff --git a/Mage/src/main/java/mage/filter/predicate/permanent/DefendingPlayerControlsPredicate.java b/Mage/src/main/java/mage/filter/predicate/permanent/DefendingPlayerControlsPredicate.java new file mode 100644 index 0000000000..ee0606669b --- /dev/null +++ b/Mage/src/main/java/mage/filter/predicate/permanent/DefendingPlayerControlsPredicate.java @@ -0,0 +1,50 @@ +/* + * 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.filter.predicate.permanent; + +import mage.filter.predicate.ObjectSourcePlayer; +import mage.filter.predicate.ObjectSourcePlayerPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * + * @author North + */ +public class DefendingPlayerControlsPredicate implements ObjectSourcePlayerPredicate> { + + @Override + public boolean apply(ObjectSourcePlayer input, Game game) { + return input.getObject().getControllerId().equals(game.getCombat().getDefendingPlayerId(input.getSourceId())); + } + + @Override + public String toString() { + return "Another"; + } +} diff --git a/Mage/src/main/java/mage/filter/predicate/permanent/DefendingPlayerOwnsCardPredicate.java b/Mage/src/main/java/mage/filter/predicate/permanent/DefendingPlayerOwnsCardPredicate.java new file mode 100644 index 0000000000..a46ebcb3d7 --- /dev/null +++ b/Mage/src/main/java/mage/filter/predicate/permanent/DefendingPlayerOwnsCardPredicate.java @@ -0,0 +1,50 @@ +/* + * 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.filter.predicate.permanent; + +import mage.cards.Card; +import mage.filter.predicate.ObjectSourcePlayer; +import mage.filter.predicate.ObjectSourcePlayerPredicate; +import mage.game.Game; + +/** + * + * @author North + */ +public class DefendingPlayerOwnsCardPredicate implements ObjectSourcePlayerPredicate> { + + @Override + public boolean apply(ObjectSourcePlayer input, Game game) { + return input.getObject().getOwnerId().equals(game.getCombat().getDefendingPlayerId(input.getSourceId())); + } + + @Override + public String toString() { + return "Another"; + } +} diff --git a/Mage/src/main/java/mage/game/permanent/token/ElephantResurgenceToken.java b/Mage/src/main/java/mage/game/permanent/token/ElephantResurgenceToken.java new file mode 100644 index 0000000000..06f4a20770 --- /dev/null +++ b/Mage/src/main/java/mage/game/permanent/token/ElephantResurgenceToken.java @@ -0,0 +1,61 @@ +/* +* 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.constants.CardType; +import mage.constants.SubType; +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount; +import mage.abilities.effects.common.continuous.SetPowerToughnessSourceEffect; +import mage.constants.Duration; +import mage.constants.Zone; +import mage.filter.common.FilterCreatureCard; + +/** + * + * @author TheElk801 + */ +public class ElephantResurgenceToken extends Token { + + public ElephantResurgenceToken() { + super("Elephant", "green Elephant creature token. Those creatures have \"This creature's power and toughness are each equal to the number of creature cards in its controller's graveyard.\""); + cardType.add(CardType.CREATURE); + color.setGreen(true); + subtype.add(SubType.ELEPHANT); + + power = new MageInt(0); + toughness = new MageInt(0); + + this.addAbility(new SimpleStaticAbility( + Zone.BATTLEFIELD, + new SetPowerToughnessSourceEffect(new CardsInControllerGraveyardCount(new FilterCreatureCard()), Duration.EndOfGame) + .setText("This creature's power and toughness are each equal to the number of creature cards in its controller's graveyard.") + )); + } +} diff --git a/Mage/src/main/java/mage/game/stack/StackAbility.java b/Mage/src/main/java/mage/game/stack/StackAbility.java index 8af807bf2d..07509f5786 100644 --- a/Mage/src/main/java/mage/game/stack/StackAbility.java +++ b/Mage/src/main/java/mage/game/stack/StackAbility.java @@ -74,6 +74,7 @@ public class StackAbility extends StackObjImpl implements Ability { private UUID controllerId; private String name; private String expansionSetCode; + private TargetAdjustment targetAdjustment = TargetAdjustment.NONE; public StackAbility(Ability ability, UUID controllerId) { this.ability = ability; @@ -86,6 +87,7 @@ public class StackAbility extends StackObjImpl implements Ability { this.controllerId = stackAbility.controllerId; this.name = stackAbility.name; this.expansionSetCode = stackAbility.expansionSetCode; + this.targetAdjustment = stackAbility.targetAdjustment; } @Override @@ -537,7 +539,7 @@ public class StackAbility extends StackObjImpl implements Ability { @Override public int getSourceObjectZoneChangeCounter() { - throw new UnsupportedOperationException("Not supported."); + return ability.getSourceObjectZoneChangeCounter(); } @Override @@ -612,4 +614,13 @@ public class StackAbility extends StackObjImpl implements Ability { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } + @Override + public void setTargetAdjustment(TargetAdjustment targetAdjustment) { + this.targetAdjustment = targetAdjustment; + } + + @Override + public TargetAdjustment getTargetAdjustment() { + return targetAdjustment; + } } diff --git a/Mage/src/main/java/mage/players/PlayerImpl.java b/Mage/src/main/java/mage/players/PlayerImpl.java index aa9321c2f6..1567246fda 100644 --- a/Mage/src/main/java/mage/players/PlayerImpl.java +++ b/Mage/src/main/java/mage/players/PlayerImpl.java @@ -1108,6 +1108,7 @@ public abstract class PlayerImpl implements Player, Serializable { if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.ACTIVATE_ABILITY, ability.getId(), ability.getSourceId(), playerId))) { int bookmark = game.bookmarkState(); ability.newId(); + ability.setControllerId(playerId); game.getStack().push(new StackAbility(ability, playerId)); if (ability.activate(game, false)) { game.fireEvent(GameEvent.getEvent(GameEvent.EventType.ACTIVATED_ABILITY, ability.getId(), ability.getSourceId(), playerId)); diff --git a/Mage/src/main/java/mage/players/net/SkipPrioritySteps.java b/Mage/src/main/java/mage/players/net/SkipPrioritySteps.java index c5c5e13a3c..1ad2853d17 100644 --- a/Mage/src/main/java/mage/players/net/SkipPrioritySteps.java +++ b/Mage/src/main/java/mage/players/net/SkipPrioritySteps.java @@ -35,13 +35,14 @@ import mage.constants.PhaseStep; * @author LevelX2 */ public class SkipPrioritySteps implements Serializable { - boolean upkeep; - boolean draw; - boolean main1; - boolean beforeCombat; - boolean endOfCombat; - boolean main2; - boolean endOfTurn; + + boolean upkeep = false; + boolean draw = false; + boolean main1 = true; + boolean beforeCombat = false; + boolean endOfCombat = false; + boolean main2 = true; + boolean endOfTurn = false; public boolean isUpkeep() { return upkeep; @@ -100,7 +101,7 @@ public class SkipPrioritySteps implements Serializable { } public boolean isPhaseStepSet(PhaseStep phaseStep) { - switch(phaseStep) { + switch (phaseStep) { case UPKEEP: return isUpkeep(); case DRAW: @@ -119,5 +120,5 @@ public class SkipPrioritySteps implements Serializable { return true; } } - + } diff --git a/Mage/src/main/java/mage/players/net/UserData.java b/Mage/src/main/java/mage/players/net/UserData.java index 888ca6b158..fec7fbcba2 100644 --- a/Mage/src/main/java/mage/players/net/UserData.java +++ b/Mage/src/main/java/mage/players/net/UserData.java @@ -79,7 +79,7 @@ public class UserData implements Serializable { } public static UserData getDefaultUserDataView() { - return new UserData(UserGroup.DEFAULT, 0, false, false, true, null, getDefaultFlagName(), false, true, true, false, false, false, false, ""); + return new UserData(UserGroup.DEFAULT, 0, false, false, true, new UserSkipPrioritySteps(), getDefaultFlagName(), false, true, true, false, false, false, false, ""); } public void setGroupId(int groupId) { diff --git a/Mage/src/main/java/mage/players/net/UserSkipPrioritySteps.java b/Mage/src/main/java/mage/players/net/UserSkipPrioritySteps.java index 9e405cc603..ee51ded5e5 100644 --- a/Mage/src/main/java/mage/players/net/UserSkipPrioritySteps.java +++ b/Mage/src/main/java/mage/players/net/UserSkipPrioritySteps.java @@ -33,15 +33,15 @@ import java.io.Serializable; * * @author LevelX2 */ - public class UserSkipPrioritySteps implements Serializable { + final SkipPrioritySteps yourTurn; final SkipPrioritySteps opponentTurn; - boolean stopOnDeclareAttackersDuringSkipAction; - boolean stopOnDeclareBlockerIfNoneAvailable; - boolean stopOnAllMainPhases; - boolean stopOnAllEndPhases; + boolean stopOnDeclareAttackersDuringSkipAction = true; + boolean stopOnDeclareBlockerIfNoneAvailable = true; + boolean stopOnAllMainPhases = true; + boolean stopOnAllEndPhases = true; public UserSkipPrioritySteps() { yourTurn = new SkipPrioritySteps(); diff --git a/Mage/src/main/java/mage/target/Target.java b/Mage/src/main/java/mage/target/Target.java index 647c6281e7..e36ef210c1 100644 --- a/Mage/src/main/java/mage/target/Target.java +++ b/Mage/src/main/java/mage/target/Target.java @@ -53,8 +53,7 @@ public interface Target extends Serializable { boolean isNotTarget(); /** - * controls if it will be checked, if the target can be targeted from - * source + * controls if it will be checked, if the target can be targeted from source * * @param notTarget true = do not check for protection, false = check for * protection @@ -113,6 +112,8 @@ public interface Target extends Serializable { int getNumberOfTargets(); + int getMinNumberOfTargets(); + int getMaxNumberOfTargets(); void setMinNumberOfTargets(int minNumberofTargets); @@ -157,8 +158,8 @@ public interface Target extends Serializable { void setTargetTag(int tag); Target getOriginalTarget(); - + // used for cards like Spellskite void setTargetAmount(UUID targetId, int amount, Game game); - + } diff --git a/Mage/src/main/java/mage/target/TargetImpl.java b/Mage/src/main/java/mage/target/TargetImpl.java index 546bafd5ad..3dbe7568cc 100644 --- a/Mage/src/main/java/mage/target/TargetImpl.java +++ b/Mage/src/main/java/mage/target/TargetImpl.java @@ -105,6 +105,11 @@ public abstract class TargetImpl implements Target { return this.minNumberOfTargets; } + @Override + public int getMinNumberOfTargets() { + return this.minNumberOfTargets; + } + @Override public int getMaxNumberOfTargets() { return this.maxNumberOfTargets;