Merge origin/master

This commit is contained in:
LevelX2 2015-10-05 14:41:02 +02:00
commit 9072fb95d7
81 changed files with 4550 additions and 355 deletions

View file

@ -100,7 +100,10 @@ public class MythicspoilerComSource implements CardImageSource {
Map<String, String> setLinks = new HashMap<>();
try {
String setNames = setsAliases.get(cardSet.toLowerCase());
Set<String> aliasesStart = cardNameAliasesStart.get(cardSet);
Set<String> aliasesStart = new HashSet<>();
if (cardNameAliasesStart.containsKey(cardSet)) {
aliasesStart.addAll(cardNameAliasesStart.get(cardSet));
}
if (setNames == null) {
setNames = cardSet.toLowerCase();
}

View file

@ -41,7 +41,7 @@ public class MageVersion implements Serializable, Comparable<MageVersion> {
public final static int MAGE_VERSION_MAJOR = 1;
public final static int MAGE_VERSION_MINOR = 4;
public final static int MAGE_VERSION_PATCH = 4;
public final static String MAGE_VERSION_MINOR_PATCH = "v7";
public final static String MAGE_VERSION_MINOR_PATCH = "v8";
public final static String MAGE_VERSION_INFO = "";
private final int major;

View file

@ -0,0 +1,52 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.alliances;
import java.util.UUID;
/**
*
* @author emerald000
*/
public class ThoughtLash extends mage.sets.masterseditionii.ThoughtLash {
public ThoughtLash(UUID ownerId) {
super(ownerId);
this.cardNumber = 58;
this.expansionSetCode = "ALL";
}
public ThoughtLash(final ThoughtLash card) {
super(card);
}
@Override
public ThoughtLash copy() {
return new ThoughtLash(this);
}
}

View file

@ -0,0 +1,166 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.antiquities;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.filter.common.FilterArtifactCard;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.stack.StackObject;
import mage.players.Player;
import mage.target.TargetCard;
import mage.target.TargetPlayer;
import mage.target.common.TargetCardInGraveyard;
/**
*
* @author emerald000
*/
public class DrafnasRestoration extends CardImpl {
public DrafnasRestoration(UUID ownerId) {
super(ownerId, 52, "Drafna's Restoration", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{U}");
this.expansionSetCode = "ATQ";
// Return any number of target artifact cards from target player's graveyard to the top of his or her library in any order.
this.getSpellAbility().addEffect(new DrafnasRestorationEffect());
this.getSpellAbility().addTarget(new TargetPlayer());
this.getSpellAbility().addTarget(new DrafnasRestorationTarget());
}
public DrafnasRestoration(final DrafnasRestoration card) {
super(card);
}
@Override
public DrafnasRestoration copy() {
return new DrafnasRestoration(this);
}
}
class DrafnasRestorationTarget extends TargetCardInGraveyard {
DrafnasRestorationTarget() {
super(0, Integer.MAX_VALUE, new FilterArtifactCard("any number of artifact cards from that player's graveyard"));
}
DrafnasRestorationTarget(final DrafnasRestorationTarget target) {
super(target);
}
@Override
public boolean canTarget(UUID id, Ability source, Game game) {
Player targetPlayer = game.getPlayer(source.getFirstTarget());
return targetPlayer != null && targetPlayer.getGraveyard().contains(id) && super.canTarget(id, source, game);
}
@Override
public Set<UUID> possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) {
Set<UUID> possibleTargets = new HashSet<>();
MageObject object = game.getObject(sourceId);
if (object != null && object instanceof StackObject) {
Player targetPlayer = game.getPlayer(((StackObject) object).getStackAbility().getFirstTarget());
if (targetPlayer != null) {
for (Card card : targetPlayer.getGraveyard().getCards(filter, sourceId, sourceControllerId, game)) {
if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.TARGET, card.getId(), sourceId, sourceControllerId))) {
possibleTargets.add(card.getId());
}
}
}
}
return possibleTargets;
}
@Override
public DrafnasRestorationTarget copy() {
return new DrafnasRestorationTarget(this);
}
}
class DrafnasRestorationEffect extends OneShotEffect {
DrafnasRestorationEffect() {
super(Outcome.Benefit);
this.staticText = "Return any number of target artifact cards from target player's graveyard to the top of his or her library in any order";
}
DrafnasRestorationEffect(final DrafnasRestorationEffect effect) {
super(effect);
}
@Override
public DrafnasRestorationEffect copy() {
return new DrafnasRestorationEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Player targetPlayer = game.getPlayer(source.getFirstTarget());
if (controller != null && targetPlayer != null) {
Cards cards = new CardsImpl(source.getTargets().get(1).getTargets()); // prevent possible ConcurrentModificationException
cards.addAll(source.getTargets().get(1).getTargets());
if (!cards.isEmpty()) {
TargetCard target = new TargetCard(Zone.PICK, new FilterCard("card to put on the top of the library (last one chosen will be topmost)"));
target.setRequired(true);
while (controller.isInGame() && cards.size() > 1) {
controller.choose(Outcome.Neutral, cards, target, game);
UUID targetId = target.getFirstTarget();
cards.remove(targetId);
target.clearChosen();
Card card = targetPlayer.getGraveyard().get(targetId, game);
if (card != null) {
controller.moveCards(card, Zone.GRAVEYARD, Zone.LIBRARY, source, game);
}
}
if (cards.size() == 1) {
Card card = targetPlayer.getGraveyard().get(cards.iterator().next(), game);
if (card != null) {
controller.moveCards(card, Zone.GRAVEYARD, Zone.LIBRARY, source, game);
}
}
}
return true;
}
return false;
}
}

View file

@ -0,0 +1,107 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.archenemy;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.keyword.MorphAbility;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.permanent.ControllerIdPredicate;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.target.common.TargetCreaturePermanent;
/**
*
* @author BursegSardaukar
*/
public class SkirkCommando extends CardImpl {
public SkirkCommando(UUID ownerId) {
super(ownerId, 47, "Skirk Commando", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{1}{R}{R}");
this.expansionSetCode = "ARC";
this.subtype.add("Goblin");
this.subtype.add("Shaman");
this.power = new MageInt(2);
this.toughness = new MageInt(1);
//Whenever Skirk Commando deals combat damage to a player, you may have it deal 2 damage to target creature that player controls.
this.addAbility(new SkirkCommandoTriggeredAbility());
//Morph {2}{R} (You may cast this card face down as a 2/2 creature for 3. Turn it face up any time for its morph cost.)
this.addAbility(new MorphAbility(this, new ManaCostsImpl("{2}{R}")));
}
public SkirkCommando(final SkirkCommando card) {
super(card);
}
@Override
public SkirkCommando copy() {
return new SkirkCommando(this);
}
}
class SkirkCommandoTriggeredAbility extends DealsCombatDamageToAPlayerTriggeredAbility {
public SkirkCommandoTriggeredAbility() {
super(new DamageTargetEffect(2), true, false);
}
public SkirkCommandoTriggeredAbility(SkirkCommandoTriggeredAbility ability) {
super(ability);
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (super.checkTrigger(event, game)) {
FilterCreaturePermanent filter = new FilterCreaturePermanent("creature that player controls");
filter.add(new ControllerIdPredicate(event.getPlayerId()));
addTarget(new TargetCreaturePermanent(filter));
}
return false;
}
@Override
public SkirkCommandoTriggeredAbility copy() {
return new SkirkCommandoTriggeredAbility(this);
}
@Override
public String getRule() {
return "Whenever {this} deals combat damage to a player, you may have it deal 2 damage to target creature that player controls.";
}
}

View file

@ -28,7 +28,7 @@
package mage.sets.commander2014;
import java.util.UUID;
import mage.abilities.condition.common.OpponentControllsMoreCondition;
import mage.abilities.condition.common.OpponentControlsMoreCondition;
import mage.abilities.decorator.ConditionalOneShotEffect;
import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect;
import mage.cards.CardImpl;
@ -60,7 +60,7 @@ public class GiftOfEstates extends CardImpl {
// If an opponent controls more lands than you, search your library for up to three Plains cards, reveal them, and put them into your hand. Then shuffle your library.
this.getSpellAbility().addEffect(new ConditionalOneShotEffect(
new SearchLibraryPutInHandEffect(new TargetCardInLibrary(0, 3, filter), true),
new OpponentControllsMoreCondition(new FilterLandPermanent("lands"))));
new OpponentControlsMoreCondition(new FilterLandPermanent("lands"))));
}
public GiftOfEstates(final GiftOfEstates card) {

View file

@ -0,0 +1,179 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.dissension;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.ExileSourceEffect;
import mage.cards.CardsImpl;
import mage.cards.SplitCard;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.filter.FilterSpell;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.mageobject.MulticoloredPredicate;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.game.stack.Spell;
import mage.players.Player;
import mage.target.common.TargetCardInYourGraveyard;
import mage.target.common.TargetControlledPermanent;
/**
*
* @author LevelX2
*/
public class BoundDetermined extends SplitCard {
private static final FilterSpell filter = new FilterSpell("multicolored spell");
static {
filter.add(new MulticoloredPredicate());
}
public BoundDetermined(UUID ownerId) {
super(ownerId, 149, "Bound", "Determined", Rarity.RARE, new CardType[]{CardType.INSTANT}, "{3}{B}{G}", "{G}{U}", false);
this.expansionSetCode = "DIS";
// Bound
// Sacrifice a creature. Return up to X cards from your graveyard to your hand, where X is the number of colors that creature was. Exile this card.
getLeftHalfCard().getSpellAbility().addEffect(new BoundEffect());
Effect effect = new ExileSourceEffect();
effect.setText("Exile this card");
getLeftHalfCard().getSpellAbility().addEffect(effect);
// Determined
// Other spells you control can't be countered by spells or abilities this turn.
// Draw a card.
getRightHalfCard().getSpellAbility().addEffect(new DeterminedEffect());
getRightHalfCard().getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1));
}
public BoundDetermined(final BoundDetermined card) {
super(card);
}
@Override
public BoundDetermined copy() {
return new BoundDetermined(this);
}
}
class BoundEffect extends OneShotEffect {
public BoundEffect() {
super(Outcome.ReturnToHand);
this.staticText = "Sacrifice a creature. Return up to X cards from your graveyard to your hand, where X is the number of colors that creature was";
}
public BoundEffect(final BoundEffect effect) {
super(effect);
}
@Override
public BoundEffect copy() {
return new BoundEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
TargetControlledPermanent target = new TargetControlledPermanent(1, 1, new FilterControlledCreaturePermanent("a creature (to sacrifice)"), true);
if (target.canChoose(source.getSourceId(), controller.getId(), game)) {
if (controller.chooseTarget(outcome, target, source, game)) {
Permanent toSacrifice = game.getPermanent(target.getFirstTarget());
if (toSacrifice != null) {
toSacrifice.sacrifice(source.getSourceId(), game);
int colors = toSacrifice.getColor(game).getColorCount();
if (colors > 0) {
TargetCardInYourGraveyard targetCard = new TargetCardInYourGraveyard(0, colors,
new FilterCard("up to " + colors + " card" + (colors > 1 ? "s" : "") + " from your graveyard"));
controller.chooseTarget(outcome, targetCard, source, game);
controller.moveCards(new CardsImpl(targetCard.getTargets()), null, Zone.HAND, source, game);
}
}
}
}
return true;
}
return false;
}
}
class DeterminedEffect extends ContinuousRuleModifyingEffectImpl {
DeterminedEffect() {
super(Duration.EndOfTurn, Outcome.Benefit);
staticText = "Other spells you control can't be countered by spells or abilities this turn";
}
DeterminedEffect(final DeterminedEffect effect) {
super(effect);
}
@Override
public DeterminedEffect copy() {
return new DeterminedEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
return true;
}
@Override
public String getInfoMessage(Ability source, GameEvent event, Game game) {
MageObject sourceObject = game.getObject(source.getSourceId());
if (sourceObject != null) {
return "This spell can't be countered (" + sourceObject.getIdName() + ").";
}
return null;
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.COUNTER;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
Spell spell = game.getStack().getSpell(event.getTargetId());
return spell != null && !spell.getSourceId().equals(source.getSourceId()) && spell.getControllerId().equals(source.getControllerId());
}
}

View file

@ -0,0 +1,156 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.dissension;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.cards.SplitCard;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.filter.common.FilterAttackingCreature;
import mage.filter.common.FilterControlledPermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.CardTypePredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.TargetPlayer;
import mage.target.common.TargetControlledPermanent;
import mage.target.targetpointer.FixedTarget;
/**
*
* @author LevelX2
*/
public class HitRun extends SplitCard {
public HitRun(UUID ownerId) {
super(ownerId, 152, "Hit", "Run", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{1}{B}{R}", "{3}{R}{G}", false);
this.expansionSetCode = "DIS";
// Hit
// Target player sacrifices an artifact or creature. Hit deals damage to that player equal to that permanent's converted mana cost.
getLeftHalfCard().getSpellAbility().addEffect(new HitEffect());
getLeftHalfCard().getSpellAbility().addTarget(new TargetPlayer());
// Run
// Attacking creatures you control get +1/+0 until end of turn for each other attacking creature.
getRightHalfCard().getSpellAbility().addEffect(new RunEffect());
}
public HitRun(final HitRun card) {
super(card);
}
@Override
public HitRun copy() {
return new HitRun(this);
}
}
class HitEffect extends OneShotEffect {
public HitEffect() {
super(Outcome.DestroyPermanent);
this.staticText = "Target player sacrifices an artifact or creature. Hit deals damage to that player equal to that permanent's converted mana cost";
}
public HitEffect(final HitEffect effect) {
super(effect);
}
@Override
public HitEffect copy() {
return new HitEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player targetPlayer = game.getPlayer(source.getTargets().getFirstTarget());
if (targetPlayer != null) {
FilterControlledPermanent filter = new FilterControlledPermanent("artifact or creature");
filter.add(Predicates.or(
new CardTypePredicate(CardType.ARTIFACT),
new CardTypePredicate(CardType.CREATURE)));
TargetControlledPermanent target = new TargetControlledPermanent(1, 1, filter, true);
if (target.canChoose(targetPlayer.getId(), game)) {
targetPlayer.choose(Outcome.Sacrifice, target, source.getSourceId(), game);
Permanent permanent = game.getPermanent(target.getFirstTarget());
if (permanent != null) {
permanent.sacrifice(source.getSourceId(), game);
int damage = permanent.getManaCost().convertedManaCost();
if (damage > 0) {
targetPlayer.damage(damage, source.getSourceId(), game, false, true);
}
}
}
}
return true;
}
}
class RunEffect extends OneShotEffect {
public RunEffect() {
super(Outcome.BoostCreature);
this.staticText = "Attacking creatures you control get +1/+0 until end of turn for each other attacking creature";
}
public RunEffect(final RunEffect effect) {
super(effect);
}
@Override
public RunEffect copy() {
return new RunEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
int attackingCreatures = game.getBattlefield().count(new FilterAttackingCreature(), controller.getId(), controller.getId(), game);
if (attackingCreatures > 1) {
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(new FilterAttackingCreature(), controller.getId(), game)) {
ContinuousEffect effect = new BoostTargetEffect(attackingCreatures - 1, 0, Duration.EndOfTurn);
effect.setTargetPointer(new FixedTarget(permanent, game));
game.addEffect(effect, source);
}
}
return true;
}
return false;
}
}

View file

@ -25,18 +25,18 @@
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.dissension;
import java.util.UUID;
import mage.abilities.effects.common.DestroyAllEffect;
import mage.abilities.effects.common.DestroyTargetEffect;
import mage.cards.SplitCard;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.cards.SplitCard;
import mage.filter.FilterPermanent;
import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.MulticoloredPredicate;
import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.target.TargetPermanent;
/**
@ -45,13 +45,11 @@ import mage.target.TargetPermanent;
*/
public class PureSimple extends SplitCard {
private static final FilterPermanent filterAura = new FilterPermanent("aura");
private static final FilterPermanent filterEquipment = new FilterPermanent("equipment");
private static final FilterPermanent filterDestroy = new FilterPermanent("Auras and Equipment");
private static final FilterPermanent filterMulticolor = new FilterPermanent("multicolor permanent");
static {
filterAura.add(new SubtypePredicate("Aura"));
filterEquipment.add(new SubtypePredicate("Equipment"));
filterDestroy.add(Predicates.or(new SubtypePredicate("Aura"), new SubtypePredicate("Equipment")));
filterMulticolor.add(new MulticoloredPredicate());
}
@ -60,15 +58,13 @@ public class PureSimple extends SplitCard {
this.expansionSetCode = "DIS";
// Pure
// Destroy all Auras
getLeftHalfCard().getSpellAbility().addEffect(new DestroyAllEffect(filterAura));
// and Equipment.
getLeftHalfCard().getSpellAbility().addEffect(new DestroyAllEffect(filterEquipment));
// Destroy target multicolored permanent.
getLeftHalfCard().getSpellAbility().addEffect(new DestroyTargetEffect());
getLeftHalfCard().getSpellAbility().addTarget(new TargetPermanent(filterMulticolor));
// Simple
// Destroy target multicolored permanent.
getRightHalfCard().getSpellAbility().addEffect(new DestroyTargetEffect());
getRightHalfCard().getSpellAbility().addTarget(new TargetPermanent(filterMulticolor));
// Destroy all Auras and Equipment.
getRightHalfCard().getSpellAbility().addEffect(new DestroyAllEffect(filterDestroy));
}
public PureSimple(final PureSimple card) {

View file

@ -39,7 +39,6 @@ import mage.filter.predicate.mageobject.MulticoloredPredicate;
import mage.game.permanent.token.SaprolingToken;
import mage.target.common.TargetCardInLibrary;
/**
*
* @author LevelX2
@ -53,16 +52,16 @@ public class SupplyDemand extends SplitCard {
}
public SupplyDemand(UUID ownerId) {
super(ownerId, 157, "Supply", "Demand", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{1}{W}{U}", "{X}{G}{W}", false);
super(ownerId, 157, "Supply", "Demand", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{X}{G}{W}", "{1}{W}{U}", false);
this.expansionSetCode = "DIS";
// Demand
// Search your library for a multicolored card, reveal it, and put it into your hand. Then shuffle your library.
getLeftHalfCard().getSpellAbility().addEffect(new SearchLibraryPutInHandEffect(new TargetCardInLibrary(1, filter), true));
// Supply
// Put X 1/1 green Saproling creature tokens onto the battlefield.
getRightHalfCard().getSpellAbility().addEffect(new CreateTokenEffect(new SaprolingToken(), new ManacostVariableValue()));
getLeftHalfCard().getSpellAbility().addEffect(new CreateTokenEffect(new SaprolingToken(), new ManacostVariableValue()));
// Demand
// Search your library for a multicolored card, reveal it, and put it into your hand. Then shuffle your library.
getRightHalfCard().getSpellAbility().addEffect(new SearchLibraryPutInHandEffect(new TargetCardInLibrary(1, filter), true));
}

View file

@ -0,0 +1,133 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.dissension;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CounterTargetEffect;
import mage.cards.Card;
import mage.cards.SplitCard;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.filter.FilterSpell;
import mage.filter.predicate.mageobject.MulticoloredPredicate;
import mage.game.Game;
import mage.game.combat.CombatGroup;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.TargetSpell;
import mage.target.common.TargetCreaturePermanent;
/**
*
* @author LevelX2
*/
public class TrialError extends SplitCard {
private static final FilterSpell filter = new FilterSpell("multicolored spell");
static {
filter.add(new MulticoloredPredicate());
}
public TrialError(UUID ownerId) {
super(ownerId, 158, "Trial", "Error", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{W}{U}", "{U}{B}", false);
this.expansionSetCode = "DIS";
// Trial
// Return all creatures blocking or blocked by target creature to their owner's hand.
getLeftHalfCard().getSpellAbility().addEffect(new TrialEffect());
getLeftHalfCard().getSpellAbility().addTarget(new TargetCreaturePermanent());
// Error
// Counter target multicolored spell.
getRightHalfCard().getSpellAbility().addEffect(new CounterTargetEffect());
getRightHalfCard().getSpellAbility().addTarget(new TargetSpell(filter));
}
public TrialError(final TrialError card) {
super(card);
}
@Override
public TrialError copy() {
return new TrialError(this);
}
}
class TrialEffect extends OneShotEffect {
public TrialEffect() {
super(Outcome.ReturnToHand);
this.staticText = "Return all creatures blocking or blocked by target creature to their owner's hand";
}
public TrialEffect(final TrialEffect effect) {
super(effect);
}
@Override
public TrialEffect copy() {
return new TrialEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Permanent creature = game.getPermanent(getTargetPointer().getFirst(game, source));
if (controller != null && creature != null) {
Set<Card> toHand = new HashSet<>();
for (CombatGroup combatGroup : game.getCombat().getGroups()) {
if (combatGroup.getBlockers().contains(creature.getId())) {
for (UUID attackerId : combatGroup.getAttackers()) {
Permanent attacker = game.getPermanent(attackerId);
if (attacker != null) {
toHand.add(attacker);
}
}
} else if (combatGroup.getAttackers().contains(creature.getId())) {
for (UUID blockerId : combatGroup.getBlockers()) {
Permanent blocker = game.getPermanent(blockerId);
if (blocker != null) {
toHand.add(blocker);
}
}
}
}
controller.moveCards(toHand, null, Zone.HAND, source, game);
return true;
}
return false;
}
}

View file

@ -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.sets.exodus;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.LicidAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.ColoredManaCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.continuous.ControlEnchantedEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.ColoredManaSymbol;
import mage.constants.Rarity;
import mage.constants.Zone;
/**
*
* @author emerald000
*/
public class DominatingLicid extends CardImpl {
public DominatingLicid(UUID ownerId) {
super(ownerId, 30, "Dominating Licid", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{1}{U}{U}");
this.expansionSetCode = "EXO";
this.subtype.add("Licid");
this.power = new MageInt(1);
this.toughness = new MageInt(1);
// {1}{U}{U}, {tap}: Dominating Licid loses this ability and becomes an Aura enchantment with enchant creature. Attach it to target creature. You may pay {U} to end this effect.
this.addAbility(new LicidAbility(new ManaCostsImpl<>("{1}{U}{U}"), new ColoredManaCost(ColoredManaSymbol.U)));
// You control enchanted creature.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ControlEnchantedEffect()));
}
public DominatingLicid(final DominatingLicid card) {
super(card);
}
@Override
public DominatingLicid copy() {
return new DominatingLicid(this);
}
}

View file

@ -0,0 +1,78 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.exodus;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.LicidAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.continuous.AddCardTypeAttachedEffect;
import mage.abilities.effects.common.continuous.BoostEnchantedEffect;
import mage.cards.CardImpl;
import mage.constants.AttachmentType;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Rarity;
import mage.constants.Zone;
/**
*
* @author emerald000
*/
public class TransmogrifyingLicid extends CardImpl {
public TransmogrifyingLicid(UUID ownerId) {
super(ownerId, 141, "Transmogrifying Licid", Rarity.UNCOMMON, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{3}");
this.expansionSetCode = "EXO";
this.subtype.add("Licid");
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// {1}, {tap}: Transmogrifying Licid loses this ability and becomes an Aura enchantment with enchant creature. Attach it to target creature. You may pay {1} to end this effect.
this.addAbility(new LicidAbility(new GenericManaCost(1), new GenericManaCost(1)));
// Enchanted creature gets +1/+1 and is an artifact in addition to its other types.
Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEnchantedEffect(1, 1));
Effect effect = new AddCardTypeAttachedEffect(CardType.ARTIFACT, Duration.WhileOnBattlefield, AttachmentType.AURA);
effect.setText("and is an artifact in addition to its other types");
ability.addEffect(effect);
this.addAbility(ability);
}
public TransmogrifyingLicid(final TransmogrifyingLicid card) {
super(card);
}
@Override
public TransmogrifyingLicid copy() {
return new TransmogrifyingLicid(this);
}
}

View file

@ -0,0 +1,84 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.guildpact;
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.costs.mana.ManaCostsImpl;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.SourcePermanentPowerCount;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.common.continuous.BoostAllEffect;
import mage.abilities.keyword.BloodthirstAbility;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.filter.common.FilterAttackingCreature;
/**
*
* @author BursegSardaukar
*/
public class RabbleRouser extends CardImpl {
public RabbleRouser(UUID ownerId) {
super(ownerId, 73, "Rabble-Rouser", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{3}{R}");
this.expansionSetCode = "GPT";
this.subtype.add("Goblin");
this.subtype.add("Shaman");
this.power = new MageInt(1);
this.toughness = new MageInt(1);
//Bloodthirst 1 (If an opponent was dealt damage this turn, this creature enters the battlefield with a +1/+1 counter on it.)
this.addAbility(new BloodthirstAbility(1));
//{R}, {T}: Attacking creatures get +X/+0 until end of turn, where X is Rabble-Rouser's power.
DynamicValue amount = new SourcePermanentPowerCount();
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD,
new BoostAllEffect(amount, new StaticValue(0), Duration.EndOfTurn, new FilterAttackingCreature(), false,
"Attacking creatures get +X/+0 until end of turn, where X is {this}'s power"),
new ManaCostsImpl("{R}"));
ability.addCost(new TapSourceCost());
this.addAbility(ability);
}
public RabbleRouser(final RabbleRouser card) {
super(card);
}
@Override
public RabbleRouser copy() {
return new RabbleRouser(this);
}
}

View file

@ -0,0 +1,88 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.iceage;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.BlocksTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.effects.common.PreventCombatDamageBySourceEffect;
import mage.abilities.effects.common.PreventCombatDamageToSourceEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.filter.common.FilterAttackingCreature;
import mage.filter.predicate.permanent.BlockedByIdPredicate;
import mage.target.common.TargetCreaturePermanent;
/**
*
* @author BursegSardaukar
*/
public class GoblinSnowman extends CardImpl {
public GoblinSnowman(UUID ownerId) {
super(ownerId, 191, "Goblin Snowman", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{3}{R}");
this.expansionSetCode = "ICE";
this.subtype.add("Goblin");
this.power = new MageInt(1);
this.toughness = new MageInt(1);
//Whenever Goblin Snowman blocks, prevent all combat damage that would be dealt to and dealt by it this turn.
Effect effect = new PreventCombatDamageBySourceEffect(Duration.EndOfTurn);
effect.setText("prevent all combat damage that would be dealt to");
Ability ability = new BlocksTriggeredAbility(effect, false);
effect = new PreventCombatDamageToSourceEffect(Duration.EndOfTurn);
effect.setText("and dealt by it this turn");
ability.addEffect(effect);
this.addAbility(ability);
//{T}: Goblin Snowman deals 1 damage to target creature it's blocking.
FilterAttackingCreature filter = new FilterAttackingCreature("creature it's blocking");
filter.add(new BlockedByIdPredicate(this.getId()));
ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(1), new TapSourceCost());
ability.addTarget(new TargetCreaturePermanent(filter));
this.addAbility(ability);
}
public GoblinSnowman(final GoblinSnowman card) {
super(card);
}
@Override
public GoblinSnowman copy() {
return new GoblinSnowman(this);
}
}

View file

@ -0,0 +1,168 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.iceage;
import java.util.UUID;
import mage.Mana;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.ReplacementEffectImpl;
import mage.abilities.keyword.CumulativeUpkeepAbility;
import mage.cards.CardImpl;
import mage.choices.Choice;
import mage.choices.ChoiceImpl;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.ManaEvent;
import mage.game.permanent.Permanent;
import mage.players.Player;
/**
*
* @author emerald000
*/
public class NakedSingularity extends CardImpl {
public NakedSingularity(UUID ownerId) {
super(ownerId, 305, "Naked Singularity", Rarity.RARE, new CardType[]{CardType.ARTIFACT}, "{5}");
this.expansionSetCode = "ICE";
// Cumulative upkeep {3}
this.addAbility(new CumulativeUpkeepAbility(new GenericManaCost(3)));
// If tapped for mana, Plains produce {R}, Islands produce {G}, Swamps produce {W}, Mountains produce {U}, and Forests produce {B} instead of any other type.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new NakedSingularityEffect()));
}
public NakedSingularity(final NakedSingularity card) {
super(card);
}
@Override
public NakedSingularity copy() {
return new NakedSingularity(this);
}
}
class NakedSingularityEffect extends ReplacementEffectImpl {
NakedSingularityEffect() {
super(Duration.WhileOnBattlefield, Outcome.Neutral);
staticText = "If tapped for mana, Plains produce {R}, Islands produce {G}, Swamps produce {W}, Mountains produce {U}, and Forests produce {B} instead of any other type";
}
NakedSingularityEffect(final NakedSingularityEffect effect) {
super(effect);
}
@Override
public NakedSingularityEffect copy() {
return new NakedSingularityEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
return true;
}
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
Permanent permanent = game.getPermanent(event.getSourceId());
Choice choice = new ChoiceImpl(true);
choice.setMessage("Pick a color to produce");
if (permanent.hasSubtype("Plains")) {
choice.getChoices().add("Red");
}
if (permanent.hasSubtype("Island")) {
choice.getChoices().add("Green");
}
if (permanent.hasSubtype("Swamp")) {
choice.getChoices().add("White");
}
if (permanent.hasSubtype("Mountain")) {
choice.getChoices().add("Blue");
}
if (permanent.hasSubtype("Forest")) {
choice.getChoices().add("Black");
}
String chosenColor;
if (choice.getChoices().size() == 1) {
chosenColor = choice.getChoices().iterator().next();
}
else {
controller.choose(Outcome.PutManaInPool, choice, game);
chosenColor = choice.getChoice();
}
ManaEvent manaEvent = (ManaEvent) event;
Mana mana = manaEvent.getMana();
int amount = mana.count();
switch (chosenColor) {
case "White":
mana.setToMana(Mana.WhiteMana(amount));
break;
case "Blue":
mana.setToMana(Mana.BlueMana(amount));
break;
case "Black":
mana.setToMana(Mana.BlackMana(amount));
break;
case "Red":
mana.setToMana(Mana.RedMana(amount));
break;
case "Green":
mana.setToMana(Mana.GreenMana(amount));
break;
}
}
return false;
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.TAPPED_FOR_MANA;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
Permanent permanent = game.getPermanent(event.getSourceId());
return permanent != null
&& (permanent.hasSubtype("Plains")
|| permanent.hasSubtype("Island")
|| permanent.hasSubtype("Swamp")
|| permanent.hasSubtype("Mountain")
|| permanent.hasSubtype("Forest"));
}
}

View file

@ -43,16 +43,15 @@ import mage.cards.CardImpl;
import mage.constants.WatcherScope;
import mage.constants.Zone;
import mage.filter.common.FilterAttackingCreature;
import mage.filter.predicate.Predicate;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.target.common.TargetCreaturePermanent;
import mage.watchers.Watcher;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import mage.filter.predicate.permanent.BlockedByIdPredicate;
/**
*
@ -75,7 +74,7 @@ public class TinderWall extends CardImpl {
this.addAbility(new SimpleManaAbility(Zone.BATTLEFIELD, new BasicManaEffect(Mana.RedMana(2)), new SacrificeSourceCost()));
// {R}, Sacrifice Tinder Wall: Tinder Wall deals 2 damage to target creature it's blocking.
FilterAttackingCreature filter = new FilterAttackingCreature("creature it's blocking");
filter.add(new BlockingByPredicate(this.getId()));
filter.add(new BlockedByIdPredicate(this.getId()));
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(2), new ManaCostsImpl("{R}"));
ability.addTarget(new TargetCreaturePermanent(filter));
ability.addCost(new SacrificeSourceCost());
@ -92,10 +91,9 @@ public class TinderWall extends CardImpl {
}
}
class BlockedByWatcher extends Watcher {
public List<UUID> blockedByWatcher = new ArrayList<UUID>();
public List<UUID> blockedByWatcher = new ArrayList<>();
public BlockedByWatcher() {
super("BlockedByWatcher", WatcherScope.CARD);
@ -127,31 +125,3 @@ class BlockedByWatcher extends Watcher {
}
}
class BlockingByPredicate implements Predicate<Permanent> {
private UUID source;
public BlockingByPredicate(UUID source) {
this.source = source;
}
@Override
public boolean apply(Permanent input, Game game) {
BlockedByWatcher watcher = (BlockedByWatcher) game.getState().getWatchers().get("BlockedByWatcher", source);
for(UUID uuid :watcher.blockedByWatcher){
Permanent creature = game.getPermanent(uuid);
if(creature != null && creature.getId().equals(input.getId())){
return true;
}
}
return false;
}
@Override
public String toString() {
return "creature it's blocking";
}
}

View file

@ -29,7 +29,7 @@ package mage.sets.legends;
import java.util.UUID;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.condition.common.OpponentControllsMoreCondition;
import mage.abilities.condition.common.OpponentControlsMoreCondition;
import mage.abilities.decorator.ConditionalTriggeredAbility;
import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect;
import mage.cards.CardImpl;
@ -53,7 +53,7 @@ public class LandTax extends CardImpl {
// At the beginning of your upkeep, if an opponent controls more lands than you, you may search your library for up to three basic land cards, reveal them, and put them into your hand. If you do, shuffle your library.
this.addAbility(new ConditionalTriggeredAbility(
new BeginningOfUpkeepTriggeredAbility(new SearchLibraryPutInHandEffect(new TargetCardInLibrary(0, 3, new FilterBasicLandCard()), true), TargetController.YOU, true),
new OpponentControllsMoreCondition(new FilterLandPermanent("lands")),
new OpponentControlsMoreCondition(new FilterLandPermanent("lands")),
"At the beginning of your upkeep, if an opponent controls more lands than you, you may search your library for up to three basic land cards, reveal them, and put them into your hand. If you do, shuffle your library"
));

View file

@ -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.sets.lorwyn;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition;
import mage.abilities.decorator.ConditionalContinuousEffect;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.continuous.BoostSourceWhileControlsEffect;
import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.filter.FilterPermanent;
/**
*
* @author BursegSardaukar
*/
public class BoggartSpriteChaser extends CardImpl {
public BoggartSpriteChaser(UUID ownerId) {
super(ownerId, 156, "Boggart Sprite-Chaser", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{1}{R}");
this.expansionSetCode = "LRW";
this.subtype.add("Goblin");
this.subtype.add("Warrior");
this.power = new MageInt(1);
this.toughness = new MageInt(2);
// As long as you control a Faerie, Boggart Sprite-Chaser gets +1/+1 and has flying.
FilterPermanent filter = new FilterPermanent("Faerie", "Faerie");
Effect effect = new BoostSourceWhileControlsEffect(filter, 1, 1);
effect.setText("As long as you control a Faerie, {this} gets +1/+1");
Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, effect);
ability.addEffect(new ConditionalContinuousEffect(
new GainAbilitySourceEffect(FlyingAbility.getInstance(), Duration.WhileOnBattlefield),
new PermanentsOnTheBattlefieldCondition(filter), "and has flying"));
this.addAbility(ability);
}
public BoggartSpriteChaser(final BoggartSpriteChaser card) {
super(card);
}
@Override
public BoggartSpriteChaser copy() {
return new BoggartSpriteChaser(this);
}
}

View file

@ -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.sets.lorwyn;
import java.util.UUID;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.abilities.costs.common.SacrificeTargetCost;
import mage.abilities.effects.common.DamageTargetControllerEffect;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.cards.CardImpl;
import mage.constants.Duration;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.target.common.TargetControlledCreaturePermanent;
import mage.target.common.TargetCreaturePermanent;
/**
* @author BursegSardaukar
*/
public class FodderLaunch extends CardImpl {
public FodderLaunch(UUID ownerId) {
super(ownerId, 114, "Fodder Launch", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{3}{B}");
this.expansionSetCode = "LRW";
this.subtype.add("Goblin");
//As an additional cost to cast Fodder Launch, sacrifice a Goblin.
this.getSpellAbility().addCost(new SacrificeTargetCost(new TargetControlledCreaturePermanent(1, 1, new FilterControlledCreaturePermanent("Goblin", "a Goblin"), true)));
//Target creature gets -5/-5 until end of turn. Fodder Launch deals 5 damage to that creature's controller.
this.getSpellAbility().addEffect(new BoostTargetEffect(-5, -5, Duration.EndOfTurn));
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
this.getSpellAbility().addEffect(new DamageTargetControllerEffect(5));
}
public FodderLaunch(final FodderLaunch card) {
super(card);
}
@Override
public FodderLaunch copy() {
return new FodderLaunch(this);
}
}

View file

@ -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.sets.lorwyn;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SpellCastAllTriggeredAbility;
import mage.abilities.effects.common.LoseLifeTargetEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.filter.FilterSpell;
import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.target.TargetPlayer;
/**
*
* @author BursegSardaukar
*/
public class QuillSlingerBoggart extends CardImpl {
private static final FilterSpell filter = new FilterSpell("a Kithkin spell");
static {
filter.add(new SubtypePredicate("Kithkin"));
}
public QuillSlingerBoggart(UUID ownerId) {
super(ownerId, 137, "Quill-Slinger Boggart", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{3}{B}");
this.expansionSetCode = "LRW";
this.subtype.add("Goblin");
this.subtype.add("Warrior");
this.power = new MageInt(3);
this.toughness = new MageInt(2);
// Whenever a player casts a Kithkin spell, you may have target player lose 1 life.
Ability ability = new SpellCastAllTriggeredAbility(new LoseLifeTargetEffect(1), filter, true);
ability.addTarget(new TargetPlayer());
this.addAbility(ability);
}
public QuillSlingerBoggart(final QuillSlingerBoggart card) {
super(card);
}
@Override
public QuillSlingerBoggart copy() {
return new QuillSlingerBoggart(this);
}
}

View file

@ -0,0 +1,182 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.masterseditionii;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.ExileFromTopOfLibraryCost;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.PreventionEffectImpl;
import mage.abilities.keyword.CumulativeUpkeepAbility;
import mage.cards.CardImpl;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.players.Player;
/**
*
* @author emerald000
*/
public class ThoughtLash extends CardImpl {
public ThoughtLash(UUID ownerId) {
super(ownerId, 70, "Thought Lash", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}{U}");
this.expansionSetCode = "ME2";
// Cumulative upkeep - Exile the top card of your library.
this.addAbility(new CumulativeUpkeepAbility(new ExileFromTopOfLibraryCost(1)));
// When a player doesn't pay Thought Lash's cumulative upkeep, that player exiles all cards from his or her library.
this.addAbility(new ThoughtLashTriggeredAbility());
// Exile the top card of your library: Prevent the next 1 damage that would be dealt to you this turn.
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new ThoughtLashPreventionEffect(), new ExileFromTopOfLibraryCost(1)));
}
public ThoughtLash(final ThoughtLash card) {
super(card);
}
@Override
public ThoughtLash copy() {
return new ThoughtLash(this);
}
}
class ThoughtLashTriggeredAbility extends TriggeredAbilityImpl {
ThoughtLashTriggeredAbility() {
super(Zone.BATTLEFIELD, new ThoughtLashExileLibraryEffect(), false);
}
ThoughtLashTriggeredAbility(final ThoughtLashTriggeredAbility ability) {
super(ability);
}
@Override
public ThoughtLashTriggeredAbility copy() {
return new ThoughtLashTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == EventType.DIDNT_PAY_CUMULATIVE_UPKEEP;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
return event.getSourceId() == this.getSourceId();
}
@Override
public String getRule() {
return "When a player doesn't pay {this}'s cumulative upkeep, that player exiles all cards from his or her library.";
}
}
class ThoughtLashExileLibraryEffect extends OneShotEffect {
ThoughtLashExileLibraryEffect() {
super(Outcome.Detriment);
this.staticText = "that player exiles all cards from his or her library";
}
ThoughtLashExileLibraryEffect(final ThoughtLashExileLibraryEffect effect) {
super(effect);
}
@Override
public ThoughtLashExileLibraryEffect copy() {
return new ThoughtLashExileLibraryEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
Cards cards = new CardsImpl();
cards.addAll(controller.getLibrary().getTopCards(game, controller.getLibrary().size()));
controller.moveCards(cards, Zone.LIBRARY, Zone.EXILED, source, game);
return true;
}
return false;
}
}
class ThoughtLashPreventionEffect extends PreventionEffectImpl {
ThoughtLashPreventionEffect() {
super(Duration.EndOfTurn);
this.staticText = "Prevent the next 1 damage that would be dealt to you this turn";
}
ThoughtLashPreventionEffect(final ThoughtLashPreventionEffect effect) {
super(effect);
}
@Override
public ThoughtLashPreventionEffect copy() {
return new ThoughtLashPreventionEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
return true;
}
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
GameEvent preventEvent = new GameEvent(GameEvent.EventType.PREVENT_DAMAGE,
source.getControllerId(), source.getSourceId(), source.getControllerId(), event.getAmount(), false);
if (!game.replaceEvent(preventEvent)) {
int damage = event.getAmount();
if (damage > 0) {
event.setAmount(damage - 1);
this.used = true;
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.PREVENTED_DAMAGE,
source.getControllerId(), source.getSourceId(), source.getControllerId(), 1));
}
}
return false;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
return !this.used && super.applies(event, source, game) && event.getTargetId().equals(source.getControllerId());
}
}

View file

@ -0,0 +1,52 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.masterseditioniv;
import java.util.UUID;
/**
*
* @author emerald000
*/
public class NakedSingularity extends mage.sets.iceage.NakedSingularity {
public NakedSingularity(UUID ownerId) {
super(ownerId);
this.cardNumber = 216;
this.expansionSetCode = "ME4";
}
public NakedSingularity(final NakedSingularity card) {
super(card);
}
@Override
public NakedSingularity copy() {
return new NakedSingularity(this);
}
}

View file

@ -0,0 +1,231 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.mirrodin;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.filter.predicate.mageobject.CardTypePredicate;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.game.stack.Spell;
import mage.players.Player;
import mage.target.common.TargetCardInASingleGraveyard;
import mage.target.targetpointer.FixedTarget;
import mage.util.CardUtil;
/**
*
* @author emerald000
*/
public class SpellweaverHelix extends CardImpl {
private static final FilterCard filter = new FilterCard("sorcery cards from a single graveyard");
static {
filter.add(new CardTypePredicate(CardType.SORCERY));
}
public SpellweaverHelix(UUID ownerId) {
super(ownerId, 247, "Spellweaver Helix", Rarity.RARE, new CardType[]{CardType.ARTIFACT}, "{3}");
this.expansionSetCode = "MRD";
// Imprint - When Spellweaver Helix enters the battlefield, you may exile two target sorcery cards from a single graveyard.
Ability ability = new EntersBattlefieldTriggeredAbility(new SpellweaverHelixImprintEffect(), true, "Imprint &mdash; ");
ability.addTarget(new TargetCardInASingleGraveyard(2, 2, filter));
this.addAbility(ability);
// Whenever a player casts a card, if it has the same name as one of the cards exiled with Spellweaver Helix, you may copy the other. If you do, you may cast the copy without paying its mana cost.
this.addAbility(new SpellweaverHelixTriggeredAbility());
}
public SpellweaverHelix(final SpellweaverHelix card) {
super(card);
}
@java.lang.Override
public SpellweaverHelix copy() {
return new SpellweaverHelix(this);
}
}
class SpellweaverHelixImprintEffect extends OneShotEffect {
SpellweaverHelixImprintEffect() {
super(Outcome.Exile);
this.staticText = "you may exile two target sorcery cards from a single graveyard";
}
SpellweaverHelixImprintEffect(final SpellweaverHelixImprintEffect effect) {
super(effect);
}
@java.lang.Override
public SpellweaverHelixImprintEffect copy() {
return new SpellweaverHelixImprintEffect(this);
}
@java.lang.Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
for (UUID targetId : this.getTargetPointer().getTargets(game, source)) {
Card card = game.getCard(targetId);
if (card != null) {
controller.moveCardsToExile(card, source, game, true, CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter()), source.getSourceObject(game).getIdName());
if (sourcePermanent != null) {
sourcePermanent.imprint(targetId, game);
}
}
}
return true;
}
return false;
}
}
class SpellweaverHelixTriggeredAbility extends TriggeredAbilityImpl {
SpellweaverHelixTriggeredAbility() {
super(Zone.BATTLEFIELD, new SpellweaverHelixCastEffect(), false);
}
SpellweaverHelixTriggeredAbility(final SpellweaverHelixTriggeredAbility ability) {
super(ability);
}
@java.lang.Override
public SpellweaverHelixTriggeredAbility copy() {
return new SpellweaverHelixTriggeredAbility(this);
}
@java.lang.Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.SPELL_CAST;
}
@java.lang.Override
public boolean checkTrigger(GameEvent event, Game game) {
Spell spell = game.getStack().getSpell(event.getTargetId());
if (spell != null && spell.getCard() != null && !spell.getCard().isCopy()) {
for (Effect effect : this.getEffects()) {
effect.setTargetPointer(new FixedTarget(spell.getId()));
}
return true;
}
return false;
}
@java.lang.Override
public boolean checkInterveningIfClause(Game game) {
Spell spell = game.getStack().getSpell(this.getEffects().get(0).getTargetPointer().getFirst(game, this));
if (spell != null) {
String spellName = spell.getName();
Permanent sourcePermanent = game.getPermanent(this.getSourceId());
if (sourcePermanent != null) {
for (UUID imprintId : sourcePermanent.getImprinted()) {
Card card = game.getCard(imprintId);
if (card != null && card.getName().equals(spellName)) {
((SpellweaverHelixCastEffect) this.getEffects().get(0)).setSpellName(spellName);
return true;
}
}
}
}
return false;
}
@java.lang.Override
public String getRule() {
return "Whenever a player casts a card, if it has the same name as one of the cards exiled with Spellweaver Helix, you may copy the other. If you do, you may cast the copy without paying its mana cost.";
}
}
class SpellweaverHelixCastEffect extends OneShotEffect {
private String spellName = "";
SpellweaverHelixCastEffect() {
super(Outcome.Benefit);
this.staticText = "you may copy the other. If you do, you may cast the copy without paying its mana cost";
}
SpellweaverHelixCastEffect(final SpellweaverHelixCastEffect effect) {
super(effect);
this.spellName = effect.spellName;
}
@java.lang.Override
public SpellweaverHelixCastEffect copy() {
return new SpellweaverHelixCastEffect(this);
}
public void setSpellName(String spellName) {
this.spellName = spellName;
}
@java.lang.Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId());
if (sourcePermanent != null) {
boolean foundSpellWithSameName = false;
for (UUID imprintId : sourcePermanent.getImprinted()) {
Card card = game.getCard(imprintId);
if (card != null) {
if (!foundSpellWithSameName && card.getName().equals(spellName)) {
foundSpellWithSameName = true;
}
else {
if (controller.chooseUse(Outcome.Copy, "Copy " + card.getIdName(), source, game)) {
Card copy = game.copyCard(card, source, source.getControllerId());
if (controller.chooseUse(Outcome.PlayForFree, "Cast " + copy.getIdName() + " without paying its mana cost?", source, game)) {
controller.cast(copy.getSpellAbility(), game, true);
}
}
}
}
}
}
return true;
}
return false;
}
}

View file

@ -0,0 +1,84 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.onslaught;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.SpellAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.continuous.GainControlTargetEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Rarity;
import mage.filter.FilterPermanent;
import mage.filter.predicate.permanent.ControllerIdPredicate;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetPermanent;
/**
*
* @author emerald000
*/
public class BlatantThievery extends CardImpl {
public BlatantThievery(UUID ownerId) {
super(ownerId, 71, "Blatant Thievery", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{4}{U}{U}{U}");
this.expansionSetCode = "ONS";
// For each opponent, gain control of target permanent that player controls.
Effect effect = new GainControlTargetEffect(Duration.EndOfGame);
effect.setText("For each opponent, gain control of target permanent that player controls");
this.getSpellAbility().addEffect(effect);
}
public BlatantThievery(final BlatantThievery card) {
super(card);
}
@Override
public void adjustTargets(Ability ability, Game game) {
if (ability instanceof SpellAbility) {
ability.getTargets().clear();
for (UUID opponentId : game.getOpponents(ability.getControllerId())) {
Player opponent = game.getPlayer(opponentId);
if (opponent != null) {
FilterPermanent filter = new FilterPermanent("permanent controlled by " + opponent.getName());
filter.add(new ControllerIdPredicate(opponentId));
ability.addTarget(new TargetPermanent(filter));
}
}
}
}
@Override
public BlatantThievery copy() {
return new BlatantThievery(this);
}
}

View file

@ -35,7 +35,7 @@ import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.ActivateIfConditionActivatedAbility;
import mage.abilities.condition.Condition;
import mage.abilities.condition.common.OpponentControllsMoreCondition;
import mage.abilities.condition.common.OpponentControlsMoreCondition;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect;
@ -67,7 +67,7 @@ public class WeatheredWayfarer extends CardImpl {
Zone.BATTLEFIELD,
new SearchLibraryPutInHandEffect(new TargetCardInLibrary(new FilterLandCard()), true, true),
new ManaCostsImpl("{W}"),
new OpponentControllsMoreCondition(new FilterLandPermanent("lands")));
new OpponentControlsMoreCondition(new FilterLandPermanent("lands")));
ability.addCost(new TapSourceCost());
this.addAbility(ability);
}

View file

@ -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.sets.planarchaos;
import java.util.UUID;
import mage.MageInt;
import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.DiscardCardCost;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.combat.CantBeBlockedByAllTargetEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.CardTypePredicate;
import mage.filter.predicate.mageobject.ColorPredicate;
import mage.target.common.TargetCreaturePermanent;
/**
*
* @author BursegSardaukar
*/
public class FirefrightMage extends CardImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("except by artifact creatures and/or red creatures");
static {
filter.add(Predicates.not(
Predicates.or(
Predicates.and(new CardTypePredicate(CardType.ARTIFACT), new CardTypePredicate(CardType.CREATURE)),
Predicates.and(new CardTypePredicate(CardType.CREATURE), new ColorPredicate(ObjectColor.RED)
))));
}
public FirefrightMage(UUID ownerId) {
super(ownerId, 99, "Firefright Mage", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{R}");
this.expansionSetCode = "PLC";
this.subtype.add("Goblin");
this.subtype.add("Spellshaper");
this.power = new MageInt(1);
this.toughness = new MageInt(1);
//{1}{R}, {T}, Discard a card: Target creature can't be blocked this turn except by artifact creatures and/or red creatures.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CantBeBlockedByAllTargetEffect(filter, Duration.EndOfTurn), new ManaCostsImpl("{1}{R}"));
ability.addCost(new TapSourceCost());
ability.addCost(new DiscardCardCost());
ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability);
}
public FirefrightMage(final FirefrightMage card) {
super(card);
}
@Override
public FirefrightMage copy() {
return new FirefrightMage(this);
}
}

View file

@ -0,0 +1,133 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.planeshift;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.RestrictionEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.filter.Filter;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.PowerPredicate;
import mage.filter.predicate.permanent.TappedPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
/**
*
* @author BursegSardaukar
*/
public class MoggJailer extends CardImpl {
static final private FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creature with power 2 or less");
static {
filter.add(Predicates.and(new PowerPredicate(Filter.ComparisonType.LessThan, 2), Predicates.not(new TappedPredicate())));
//filter.add(new PowerPredicate(Filter.ComparisonType.LessThan, 3));
}
public MoggJailer(UUID ownerId) {
super(ownerId, 68, "Mogg Jailer", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{1}{R}");
this.expansionSetCode = "PLS";
this.subtype.add("Goblin");
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// Mogg Jailer can't attack if defending player controls an untapped creature with power 2 or less.
Effect effect = new CantAttackIfDefenderControllsPermanent(filter);
effect.setText("Mogg Jailer can't attack if defending player controls an untapped creature with power 2 or less.");
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect));
}
public MoggJailer(final MoggJailer card) {
super(card);
}
@Override
public MoggJailer copy() {
return new MoggJailer(this);
}
}
class CantAttackIfDefenderControllsPermanent extends RestrictionEffect {
private final FilterPermanent filter;
public CantAttackIfDefenderControllsPermanent(FilterPermanent filter) {
super(Duration.WhileOnBattlefield);
this.filter = filter;
staticText = new StringBuilder("{this} can't attack if defending player controls ").append(filter.getMessage()).toString();
}
public CantAttackIfDefenderControllsPermanent(final CantAttackIfDefenderControllsPermanent effect) {
super(effect);
this.filter = effect.filter;
}
@Override
public boolean applies(Permanent permanent, Ability source, Game game) {
return permanent.getId().equals(source.getSourceId());
}
@Override
public boolean canAttack(UUID defenderId, Ability source, Game game) {
UUID defendingPlayerId;
Player player = game.getPlayer(defenderId);
if (player == null) {
Permanent permanent = game.getPermanent(defenderId);
if (permanent != null) {
defendingPlayerId = permanent.getControllerId();
} else {
return true;
}
} else {
defendingPlayerId = defenderId;
}
if (defendingPlayerId != null && game.getBattlefield().countAll(filter, defendingPlayerId, game) > 0) {
return false;
}
return true;
}
@Override
public CantAttackIfDefenderControllsPermanent copy() {
return new CantAttackIfDefenderControllsPermanent(this);
}
}

View file

@ -0,0 +1,164 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.ravnica;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.continuous.GainAbilityAllEffect;
import mage.abilities.keyword.DoubleStrikeAbility;
import mage.abilities.keyword.FearAbility;
import mage.abilities.keyword.FirstStrikeAbility;
import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.LandwalkAbility;
import mage.abilities.keyword.ProtectionAbility;
import mage.abilities.keyword.TrampleAbility;
import mage.abilities.keyword.VigilanceAbility;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.TargetController;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.mageobject.AbilityPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
/**
*
* @author emerald000
*/
public class ConcertedEffort extends CardImpl {
public ConcertedEffort(UUID ownerId) {
super(ownerId, 8, "Concerted Effort", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}{W}");
this.expansionSetCode = "RAV";
// At the beginning of each upkeep, creatures you control gain flying until end of turn if a creature you control has flying. The same is true for fear, first strike, double strike, landwalk, protection, trample, and vigilance.
this.addAbility(new BeginningOfUpkeepTriggeredAbility(new ConcertedEffortEffect(), TargetController.ANY, false));
}
public ConcertedEffort(final ConcertedEffort card) {
super(card);
}
@Override
public ConcertedEffort copy() {
return new ConcertedEffort(this);
}
}
class ConcertedEffortEffect extends OneShotEffect {
private static final FilterCreaturePermanent filterFlying = new FilterCreaturePermanent();
private static final FilterCreaturePermanent filterFear = new FilterCreaturePermanent();
private static final FilterCreaturePermanent filterFirstStrike = new FilterCreaturePermanent();
private static final FilterCreaturePermanent filterDoubleStrike = new FilterCreaturePermanent();
private static final FilterCreaturePermanent filterLandwalk = new FilterCreaturePermanent();
private static final FilterCreaturePermanent filterProtection = new FilterCreaturePermanent();
private static final FilterCreaturePermanent filterTrample = new FilterCreaturePermanent();
private static final FilterCreaturePermanent filterVigilance = new FilterCreaturePermanent();
static {
filterFlying.add(new AbilityPredicate(FlyingAbility.class));
filterFear.add(new AbilityPredicate(FearAbility.class));
filterFirstStrike.add(new AbilityPredicate(FirstStrikeAbility.class));
filterDoubleStrike.add(new AbilityPredicate(DoubleStrikeAbility.class));
filterLandwalk.add(new AbilityPredicate(LandwalkAbility.class));
filterProtection.add(new AbilityPredicate(ProtectionAbility.class));
filterTrample.add(new AbilityPredicate(TrampleAbility.class));
filterVigilance.add(new AbilityPredicate(VigilanceAbility.class));
}
ConcertedEffortEffect() {
super(Outcome.BoostCreature);
this.staticText = "creatures you control gain flying until end of turn if a creature you control has flying. The same is true for fear, first strike, double strike, landwalk, protection, trample, and vigilance";
}
ConcertedEffortEffect(final ConcertedEffortEffect effect) {
super(effect);
}
@Override
public ConcertedEffortEffect copy() {
return new ConcertedEffortEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
// Flying
if (game.getBattlefield().contains(filterFlying, source.getControllerId(), 1, game)) {
game.addEffect(new GainAbilityAllEffect(FlyingAbility.getInstance(), Duration.EndOfTurn), source);
}
// Fear
if (game.getBattlefield().contains(filterFear, source.getControllerId(), 1, game)) {
game.addEffect(new GainAbilityAllEffect(FearAbility.getInstance(), Duration.EndOfTurn), source);
}
// First strike
if (game.getBattlefield().contains(filterFirstStrike, source.getControllerId(), 1, game)) {
game.addEffect(new GainAbilityAllEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn), source);
}
// Double strike
if (game.getBattlefield().contains(filterDoubleStrike, source.getControllerId(), 1, game)) {
game.addEffect(new GainAbilityAllEffect(DoubleStrikeAbility.getInstance(), Duration.EndOfTurn), source);
}
// Landwalk
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filterLandwalk, source.getControllerId(), game)) {
for (Ability ability : permanent.getAbilities(game)) {
if (ability instanceof LandwalkAbility) {
game.addEffect(new GainAbilityAllEffect(ability, Duration.EndOfTurn), source);
}
}
}
// Protection
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filterProtection, source.getControllerId(), game)) {
for (Ability ability : permanent.getAbilities(game)) {
if (ability instanceof ProtectionAbility) {
game.addEffect(new GainAbilityAllEffect(ability, Duration.EndOfTurn), source);
}
}
}
// Trample
if (game.getBattlefield().contains(filterTrample, source.getControllerId(), 1, game)) {
game.addEffect(new GainAbilityAllEffect(TrampleAbility.getInstance(), Duration.EndOfTurn), source);
}
// Vigilance
if (game.getBattlefield().contains(filterVigilance, source.getControllerId(), 1, game)) {
game.addEffect(new GainAbilityAllEffect(VigilanceAbility.getInstance(), Duration.EndOfTurn), source);
}
return true;
}
}

View file

@ -0,0 +1,78 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.ravnica;
import java.util.UUID;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.MageInt;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.combat.MustBeBlockedByAtLeastOneSourceEffect;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.abilities.keyword.HasteAbility;
import mage.cards.CardImpl;
import mage.constants.Duration;
import mage.constants.Zone;
/**
*
* @author BursegSardaukar
*/
public class GoblinFireFiend extends CardImpl {
public GoblinFireFiend(UUID ownerId) {
super(ownerId, 127, "Goblin Fire Fiend", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{3}{R}");
this.expansionSetCode = "RAV";
this.subtype.add("Goblin");
this.subtype.add("Berserker");
this.power = new MageInt(1);
this.toughness = new MageInt(1);
//Haste
this.addAbility(HasteAbility.getInstance());
//Goblin Fire Fiend must be blocked if able.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new MustBeBlockedByAtLeastOneSourceEffect()));
//{R}: Goblin Fire Fiend gets +1/+0 until end of turn.
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostSourceEffect(1, 0, Duration.EndOfTurn), new ManaCostsImpl("{R}")));
}
public GoblinFireFiend(final GoblinFireFiend card) {
super(card);
}
@Override
public GoblinFireFiend copy() {
return new GoblinFireFiend(this);
}
}

View file

@ -58,7 +58,7 @@ public class AEthertow extends CardImpl {
this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter));
// Conspire
this.addAbility(new ConspireAbility(this));
this.addAbility(new ConspireAbility(getId(), ConspireAbility.ConspireTargets.ONE));
}
public AEthertow(final AEthertow card) {

View file

@ -51,7 +51,7 @@ public class BarkshellBlessing extends CardImpl {
this.getSpellAbility().addEffect(new BoostTargetEffect(2, 2, Duration.EndOfTurn));
// Conspire
this.addAbility(new ConspireAbility(this));
this.addAbility(new ConspireAbility(getId(), ConspireAbility.ConspireTargets.ONE));
}
public BarkshellBlessing(final BarkshellBlessing card) {

View file

@ -50,7 +50,7 @@ public class BurnTrail extends CardImpl {
this.getSpellAbility().addTarget(new TargetCreatureOrPlayer());
// Conspire
this.addAbility(new ConspireAbility(this));
this.addAbility(new ConspireAbility(getId(), ConspireAbility.ConspireTargets.ONE));
}
public BurnTrail(final BurnTrail card) {

View file

@ -51,7 +51,7 @@ public class DisturbingPlot extends CardImpl {
this.getSpellAbility().addTarget(new TargetCardInGraveyard(new FilterCreatureCard("creature card in a graveyard")));
// Conspire
this.addAbility(new ConspireAbility(this));
this.addAbility(new ConspireAbility(getId(), ConspireAbility.ConspireTargets.ONE));
}

View file

@ -52,7 +52,7 @@ public class GhastlyDiscovery extends CardImpl {
this.getSpellAbility().addEffect(new GhastlyDiscoveryEffect());
// Conspire
this.addAbility(new ConspireAbility(this));
this.addAbility(new ConspireAbility(getId(), ConspireAbility.ConspireTargets.NONE));
}
public GhastlyDiscovery(final GhastlyDiscovery card) {

View file

@ -58,7 +58,7 @@ public class Giantbaiting extends CardImpl {
this.getSpellAbility().addEffect(new GiantbaitingEffect());
// Conspire
this.addAbility(new ConspireAbility(this));
this.addAbility(new ConspireAbility(getId(), ConspireAbility.ConspireTargets.NONE));
}

View file

@ -51,7 +51,7 @@ public class GleefulSabotage extends CardImpl {
this.getSpellAbility().addTarget(new TargetPermanent(new FilterArtifactOrEnchantmentPermanent()));
// Conspire
this.addAbility(new ConspireAbility(this));
this.addAbility(new ConspireAbility(getId(), ConspireAbility.ConspireTargets.ONE));
}
public GleefulSabotage(final GleefulSabotage card) {

View file

@ -50,7 +50,7 @@ public class MemorySluice extends CardImpl {
this.getSpellAbility().addTarget(new TargetPlayer());
// Conspire
this.addAbility(new ConspireAbility(this));
this.addAbility(new ConspireAbility(getId(), ConspireAbility.ConspireTargets.ONE));
}

View file

@ -60,7 +60,7 @@ public class MineExcavation extends CardImpl {
this.getSpellAbility().addTarget(new TargetCardInGraveyard(filter));
// Conspire
this.addAbility(new ConspireAbility(this));
this.addAbility(new ConspireAbility(getId(), ConspireAbility.ConspireTargets.ONE));
}
public MineExcavation(final MineExcavation card) {

View file

@ -53,6 +53,7 @@ public class RattleblazeScarecrow extends CardImpl {
private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("a black creature");
private static final FilterControlledCreaturePermanent filter2 = new FilterControlledCreaturePermanent("a red creature");
static {
filter.add(new ColorPredicate(ObjectColor.BLACK));
filter2.add(new ColorPredicate(ObjectColor.RED));
@ -74,7 +75,7 @@ public class RattleblazeScarecrow extends CardImpl {
// Rattleblaze Scarecrow has haste as long as you control a red creature.
ContinuousEffect effect2 = new GainAbilitySourceEffect(HasteAbility.getInstance(), Duration.WhileOnBattlefield);
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(effect2, new PermanentsOnTheBattlefieldCondition(filter), rule2)));
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(effect2, new PermanentsOnTheBattlefieldCondition(filter2), rule2)));
}

View file

@ -64,7 +64,7 @@ public class TraitorsRoar extends CardImpl {
this.getSpellAbility().addEffect(new TraitorsRoarEffect());
// Conspire
this.addAbility(new ConspireAbility(this));
this.addAbility(new ConspireAbility(getId(), ConspireAbility.ConspireTargets.ONE));
}

View file

@ -0,0 +1,139 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.shadowmoor;
import java.util.UUID;
import mage.MageInt;
import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.keyword.ConspireAbility;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Layer;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.SubLayer;
import mage.constants.Zone;
import mage.filter.common.FilterInstantOrSorcerySpell;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.ColorPredicate;
import mage.game.Game;
import mage.game.permanent.token.Token;
import mage.game.stack.Spell;
import mage.game.stack.StackObject;
/**
*
* @author LevelX2
*/
public class WortTheRaidmother extends CardImpl {
public WortTheRaidmother(UUID ownerId) {
super(ownerId, 223, "Wort, the Raidmother", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{4}{R/G}{R/G}");
this.expansionSetCode = "SHM";
this.supertype.add("Legendary");
this.subtype.add("Goblin");
this.subtype.add("Shaman");
this.power = new MageInt(3);
this.toughness = new MageInt(3);
// When Wort, the Raidmother enters the battlefield, put two 1/1 red and green Goblin Warrior creature tokens onto the battlefield.
this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new WortTheRaidmotherToken(), 2), false));
// Each red or green instant or sorcery spell you cast has conspire.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new WortGainConspireEffect()));
}
public WortTheRaidmother(final WortTheRaidmother card) {
super(card);
}
@Override
public WortTheRaidmother copy() {
return new WortTheRaidmother(this);
}
}
class WortGainConspireEffect extends ContinuousEffectImpl {
private final static FilterInstantOrSorcerySpell filter = new FilterInstantOrSorcerySpell();
static {
filter.add(Predicates.or(new ColorPredicate(ObjectColor.RED), new ColorPredicate(ObjectColor.GREEN)));
}
private final ConspireAbility conspireAbility;
public WortGainConspireEffect() {
super(Duration.WhileOnBattlefield, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility);
staticText = "Each red or green instant or sorcery spell you cast has conspire. <i>(As you cast the spell, you may tap two untapped creatures you control that share a color with it. When you do, copy it and you may choose new targets for the copy.)</i>";
conspireAbility = new ConspireAbility(getId(), ConspireAbility.ConspireTargets.MORE);
}
public WortGainConspireEffect(final WortGainConspireEffect effect) {
super(effect);
this.conspireAbility = new ConspireAbility(getId(), ConspireAbility.ConspireTargets.MORE);
}
@Override
public WortGainConspireEffect copy() {
return new WortGainConspireEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
for (StackObject stackObject : game.getStack()) {
// only spells cast, so no copies of spells
if ((stackObject instanceof Spell) && !stackObject.isCopy() && stackObject.getControllerId().equals(source.getControllerId())) {
Spell spell = (Spell) stackObject;
if (filter.match(stackObject, game)) {
game.getState().addOtherAbility(spell.getCard(), conspireAbility);
}
}
}
return true;
}
}
class WortTheRaidmotherToken extends Token {
public WortTheRaidmotherToken() {
super("Goblin Warrior", "1/1 red and green Goblin Warrior creature token");
cardType.add(CardType.CREATURE);
color.setRed(true);
color.setGreen(true);
subtype.add("Goblin");
subtype.add("Warrior");
power = new MageInt(1);
toughness = new MageInt(1);
}
}

View file

@ -33,7 +33,7 @@ import mage.constants.CardType;
import mage.constants.Rarity;
import mage.MageInt;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.condition.common.OpponentControllsMoreCondition;
import mage.abilities.condition.common.OpponentControlsMoreCondition;
import mage.abilities.decorator.ConditionalTriggeredAbility;
import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect;
import mage.abilities.keyword.FirstStrikeAbility;
@ -63,7 +63,7 @@ public class KnightOfTheWhiteOrchid extends CardImpl {
// When Knight of the White Orchid enters the battlefield, if an opponent controls more lands than you, you may search your library for a Plains card, put it onto the battlefield, then shuffle your library.
this.addAbility(new ConditionalTriggeredAbility(
new EntersBattlefieldTriggeredAbility(new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(0, 1, new FilterBySubtypeCard("Plains")), false), true),
new OpponentControllsMoreCondition(new FilterLandPermanent("lands")),
new OpponentControlsMoreCondition(new FilterLandPermanent("lands")),
"When {this} enters the battlefield, if an opponent controls more lands than you, you may search your library for a Plains card, put it onto the battlefield, then shuffle your library"));
}

View file

@ -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.sets.stronghold;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.LicidAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.ColoredManaCost;
import mage.abilities.effects.common.combat.CantAttackAttachedEffect;
import mage.cards.CardImpl;
import mage.constants.AttachmentType;
import mage.constants.CardType;
import mage.constants.ColoredManaSymbol;
import mage.constants.Rarity;
import mage.constants.Zone;
/**
*
* @author emerald000
*/
public class CalmingLicid extends CardImpl {
public CalmingLicid(UUID ownerId) {
super(ownerId, 102, "Calming Licid", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{2}{W}");
this.expansionSetCode = "STH";
this.subtype.add("Licid");
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// {W}, {tap}: Calming Licid loses this ability and becomes an Aura enchantment with enchant creature. Attach it to target creature. You may pay {W} to end this effect.
this.addAbility(new LicidAbility(new ColoredManaCost(ColoredManaSymbol.W), new ColoredManaCost(ColoredManaSymbol.W)));
// Enchanted creature can't attack.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantAttackAttachedEffect(AttachmentType.AURA)));
}
public CalmingLicid(final CalmingLicid card) {
super(card);
}
@Override
public CalmingLicid copy() {
return new CalmingLicid(this);
}
}

View file

@ -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.sets.stronghold;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.LicidAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.ColoredManaCost;
import mage.abilities.effects.common.combat.CantBlockAttachedEffect;
import mage.cards.CardImpl;
import mage.constants.AttachmentType;
import mage.constants.CardType;
import mage.constants.ColoredManaSymbol;
import mage.constants.Rarity;
import mage.constants.Zone;
/**
*
* @author emerald000
*/
public class ConvulsingLicid extends CardImpl {
public ConvulsingLicid(UUID ownerId) {
super(ownerId, 77, "Convulsing Licid", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{2}{R}");
this.expansionSetCode = "STH";
this.subtype.add("Licid");
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// {R}, {tap}: Convulsing Licid loses this ability and becomes an Aura enchantment with enchant creature. Attach it to target creature. You may pay {R} to end this effect.
this.addAbility(new LicidAbility(new ColoredManaCost(ColoredManaSymbol.R), new ColoredManaCost(ColoredManaSymbol.R)));
// Enchanted creature can't block.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantBlockAttachedEffect(AttachmentType.AURA)));
}
public ConvulsingLicid(final ConvulsingLicid card) {
super(card);
}
@Override
public ConvulsingLicid copy() {
return new ConvulsingLicid(this);
}
}

View file

@ -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.sets.stronghold;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.LicidAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.ColoredManaCost;
import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect;
import mage.abilities.keyword.FearAbility;
import mage.cards.CardImpl;
import mage.constants.AttachmentType;
import mage.constants.CardType;
import mage.constants.ColoredManaSymbol;
import mage.constants.Rarity;
import mage.constants.Zone;
/**
*
* @author emerald000
*/
public class CorruptingLicid extends CardImpl {
public CorruptingLicid(UUID ownerId) {
super(ownerId, 4, "Corrupting Licid", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{2}{B}");
this.expansionSetCode = "STH";
this.subtype.add("Licid");
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// {B}, {tap}: Corrupting Licid loses this ability and becomes an Aura enchantment with enchant creature. Attach it to target creature. You may pay {B} to end this effect.
this.addAbility(new LicidAbility(new ColoredManaCost(ColoredManaSymbol.B), new ColoredManaCost(ColoredManaSymbol.B)));
// Enchanted creature has fear.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(FearAbility.getInstance(), AttachmentType.AURA)));
}
public CorruptingLicid(final CorruptingLicid card) {
super(card);
}
@Override
public CorruptingLicid copy() {
return new CorruptingLicid(this);
}
}

View file

@ -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.sets.stronghold;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.LicidAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.ColoredManaCost;
import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.constants.AttachmentType;
import mage.constants.CardType;
import mage.constants.ColoredManaSymbol;
import mage.constants.Rarity;
import mage.constants.Zone;
/**
*
* @author emerald000
*/
public class GlidingLicid extends CardImpl {
public GlidingLicid(UUID ownerId) {
super(ownerId, 31, "Gliding Licid", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{2}{U}");
this.expansionSetCode = "STH";
this.subtype.add("Licid");
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// {U}, {tap}: Gliding Licid loses this ability and becomes an Aura enchantment with enchant creature. Attach it to target creature. You may pay {U} to end this effect.
this.addAbility(new LicidAbility(new ColoredManaCost(ColoredManaSymbol.U), new ColoredManaCost(ColoredManaSymbol.U)));
// Enchanted creature has flying.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(FlyingAbility.getInstance(), AttachmentType.AURA)));
}
public GlidingLicid(final GlidingLicid card) {
super(card);
}
@Override
public GlidingLicid copy() {
return new GlidingLicid(this);
}
}

View file

@ -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.sets.stronghold;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.LicidAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.ColoredManaCost;
import mage.abilities.effects.common.combat.MustBeBlockedByAllAttachedEffect;
import mage.cards.CardImpl;
import mage.constants.AttachmentType;
import mage.constants.CardType;
import mage.constants.ColoredManaSymbol;
import mage.constants.Rarity;
import mage.constants.Zone;
/**
*
* @author emerald000
*/
public class TemptingLicid extends CardImpl {
public TemptingLicid(UUID ownerId) {
super(ownerId, 72, "Tempting Licid", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{2}{G}");
this.expansionSetCode = "STH";
this.subtype.add("Licid");
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// {G}, {tap}: Tempting Licid loses this ability and becomes an Aura enchantment with enchant creature. Attach it to target creature. You may pay {G} to end this effect.
this.addAbility(new LicidAbility(new ColoredManaCost(ColoredManaSymbol.G), new ColoredManaCost(ColoredManaSymbol.G)));
// All creatures able to block enchanted creature do so.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new MustBeBlockedByAllAttachedEffect(AttachmentType.AURA)));
}
public TemptingLicid(final TemptingLicid card) {
super(card);
}
@Override
public TemptingLicid copy() {
return new TemptingLicid(this);
}
}

View file

@ -0,0 +1,74 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.tempest;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.common.LicidAbility;
import mage.abilities.costs.mana.ColoredManaCost;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.ColoredManaSymbol;
import mage.constants.Rarity;
import mage.constants.TargetController;
import mage.constants.Zone;
/**
*
* @author emerald000
*/
public class LeechingLicid extends CardImpl {
public LeechingLicid(UUID ownerId) {
super(ownerId, 35, "Leeching Licid", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{1}{B}");
this.expansionSetCode = "TMP";
this.subtype.add("Licid");
this.power = new MageInt(1);
this.toughness = new MageInt(1);
// {B}, {tap}: Leeching Licid loses this ability and becomes an Aura enchantment with enchant creature. Attach it to target creature. You may pay {B} to end this effect.
this.addAbility(new LicidAbility(new ColoredManaCost(ColoredManaSymbol.B), new ColoredManaCost(ColoredManaSymbol.B)));
// At the beginning of the upkeep of enchanted creature's controller, Leeching Licid deals 1 damage to that player.
Effect effect = new DamageTargetEffect(1);
effect.setText("{this} deals 1 damage to that player");
this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, effect, TargetController.CONTROLLER_ATTACHED_TO, false, true));
}
public LeechingLicid(final LeechingLicid card) {
super(card);
}
@Override
public LeechingLicid copy() {
return new LeechingLicid(this);
}
}

View file

@ -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.sets.tempest;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.dynamicvalue.common.SignInversionDynamicValue;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.permanent.AnotherPredicate;
/**
*
* @author BursegSardaukar
*/
public class MoggSquad extends CardImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("each other creature on the battlefield");
static {
filter.add(new AnotherPredicate());
}
public MoggSquad(UUID ownerId) {
super(ownerId, 192, "Mogg Squad", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{1}{R}");
this.expansionSetCode = "TMP";
this.subtype.add("Goblin");
this.power = new MageInt(3);
this.toughness = new MageInt(3);
// Mogg Squad gets -1/-1 for each other creature on the battlefield.
DynamicValue amount = new SignInversionDynamicValue(new PermanentsOnBattlefieldCount(filter));
Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostSourceEffect(amount, amount, Duration.WhileOnBattlefield));
this.addAbility(ability);
}
public MoggSquad(final MoggSquad card) {
super(card);
}
@Override
public MoggSquad copy() {
return new MoggSquad(this);
}
}

View file

@ -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.sets.tempest;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.LicidAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ColoredManaCost;
import mage.abilities.effects.common.RegenerateAttachedEffect;
import mage.cards.CardImpl;
import mage.constants.AttachmentType;
import mage.constants.CardType;
import mage.constants.ColoredManaSymbol;
import mage.constants.Rarity;
import mage.constants.Zone;
/**
*
* @author emerald000
*/
public class NurturingLicid extends CardImpl {
public NurturingLicid(UUID ownerId) {
super(ownerId, 136, "Nurturing Licid", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{1}{G}");
this.expansionSetCode = "TMP";
this.subtype.add("Licid");
this.power = new MageInt(1);
this.toughness = new MageInt(1);
// {G}, {tap}: Nurturing Licid loses this ability and becomes an Aura enchantment with enchant creature. Attach it to target creature. You may pay {G} to end this effect.
this.addAbility(new LicidAbility(new ColoredManaCost(ColoredManaSymbol.G), new ColoredManaCost(ColoredManaSymbol.G)));
// {G}: Regenerate enchanted creature.
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new RegenerateAttachedEffect(AttachmentType.AURA), new ColoredManaCost(ColoredManaSymbol.G)));
}
public NurturingLicid(final NurturingLicid card) {
super(card);
}
@Override
public NurturingLicid copy() {
return new NurturingLicid(this);
}
}

View file

@ -0,0 +1,73 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.tempest;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.LicidAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.ColoredManaCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect;
import mage.abilities.keyword.FirstStrikeAbility;
import mage.cards.CardImpl;
import mage.constants.AttachmentType;
import mage.constants.CardType;
import mage.constants.ColoredManaSymbol;
import mage.constants.Rarity;
import mage.constants.Zone;
/**
*
* @author emerald000
*/
public class QuickeningLicid extends CardImpl {
public QuickeningLicid(UUID ownerId) {
super(ownerId, 248, "Quickening Licid", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{1}{W}");
this.expansionSetCode = "TMP";
this.subtype.add("Licid");
this.power = new MageInt(1);
this.toughness = new MageInt(1);
// {1}{W}, {tap}: Quickening Licid loses this ability and becomes an Aura enchantment with enchant creature. Attach it to target creature. You may pay {W} to end this effect.
this.addAbility(new LicidAbility(new ManaCostsImpl<>("{1}{W}"), new ColoredManaCost(ColoredManaSymbol.W)));
// Enchanted creature has first strike.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(FirstStrikeAbility.getInstance(), AttachmentType.AURA)));
}
public QuickeningLicid(final QuickeningLicid card) {
super(card);
}
@Override
public QuickeningLicid copy() {
return new QuickeningLicid(this);
}
}

View file

@ -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.sets.tempest;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.BecomesTappedAttachedTriggeredAbility;
import mage.abilities.common.LicidAbility;
import mage.abilities.costs.mana.ColoredManaCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.DamageAttachedControllerEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.ColoredManaSymbol;
import mage.constants.Rarity;
/**
*
* @author emerald000
*/
public class StingingLicid extends CardImpl {
public StingingLicid(UUID ownerId) {
super(ownerId, 91, "Stinging Licid", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{1}{U}");
this.expansionSetCode = "TMP";
this.subtype.add("Licid");
this.power = new MageInt(1);
this.toughness = new MageInt(1);
// {1}{U}, {tap}: Stinging Licid loses this ability and becomes an Aura enchantment with enchant creature. Attach it to target creature. You may pay {U} to end this effect.
this.addAbility(new LicidAbility(new ManaCostsImpl<>("{1}{U}"), new ColoredManaCost(ColoredManaSymbol.U)));
// Whenever enchanted creature becomes tapped, Stinging Licid deals 2 damage to that creature's controller.
this.addAbility(new BecomesTappedAttachedTriggeredAbility(new DamageAttachedControllerEffect(2), "enchanted creature"));
}
public StingingLicid(final StingingLicid card) {
super(card);
}
@Override
public StingingLicid copy() {
return new StingingLicid(this);
}
}

View file

@ -0,0 +1,52 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.timeshifted;
import java.util.UUID;
/**
*
* @author BursegSardaukar
*/
public class GoblinSnowman extends mage.sets.iceage.GoblinSnowman {
public GoblinSnowman(UUID ownerId) {
super(ownerId);
this.cardNumber = 64;
this.expansionSetCode = "TSB";
}
public GoblinSnowman(final GoblinSnowman card) {
super(card);
}
@Override
public GoblinSnowman copy() {
return new GoblinSnowman(this);
}
}

View file

@ -0,0 +1,144 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.torment;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.UUID;
import mage.MageInt;
import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.common.LeavesBattlefieldTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.common.PayLifeCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ExileAllEffect;
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
import mage.abilities.effects.common.continuous.BecomesColorTargetEffect;
import mage.abilities.effects.common.continuous.BecomesSubtypeTargetEffect;
import mage.abilities.effects.common.continuous.BoostAllEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterCreatureCard;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetCardInGraveyard;
import mage.target.targetpointer.FixedTarget;
/**
*
* @author emerald000
*/
public class ChainerDementiaMaster extends CardImpl {
private static final FilterCreaturePermanent filterCreature = new FilterCreaturePermanent("Nightmare creatures");
private static final FilterPermanent filterPermanent = new FilterPermanent("Nightmares");
static {
filterCreature.add(new SubtypePredicate("Nightmare"));
filterPermanent.add(new SubtypePredicate("Nightmare"));
}
public ChainerDementiaMaster(UUID ownerId) {
super(ownerId, 56, "Chainer, Dementia Master", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{3}{B}{B}");
this.expansionSetCode = "TOR";
this.supertype.add("Legendary");
this.subtype.add("Human");
this.subtype.add("Minion");
this.power = new MageInt(3);
this.toughness = new MageInt(3);
// Nightmare creatures get +1/+1.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostAllEffect(1, 1, Duration.WhileOnBattlefield, filterCreature, false)));
// {B}{B}{B}, Pay 3 life: Put target creature card from a graveyard onto the battlefield under your control. That creature is black and is a Nightmare in addition to its other creature types.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ChainerDementiaMasterEffect(), new ManaCostsImpl<>("{B}{B}{B}"));
ability.addCost(new PayLifeCost(3));
ability.addTarget(new TargetCardInGraveyard(new FilterCreatureCard("creature card from a graveyard")));
this.addAbility(ability);
// When Chainer, Dementia Master leaves the battlefield, exile all Nightmares.
this.addAbility(new LeavesBattlefieldTriggeredAbility(new ExileAllEffect(filterPermanent), false));
}
public ChainerDementiaMaster(final ChainerDementiaMaster card) {
super(card);
}
@Override
public ChainerDementiaMaster copy() {
return new ChainerDementiaMaster(this);
}
}
class ChainerDementiaMasterEffect extends OneShotEffect {
ChainerDementiaMasterEffect() {
super(Outcome.PutCreatureInPlay);
this.staticText = "Put target creature card from a graveyard onto the battlefield under your control. That creature is black and is a Nightmare in addition to its other creature types";
}
ChainerDementiaMasterEffect(final ChainerDementiaMasterEffect effect) {
super(effect);
}
@Override
public ChainerDementiaMasterEffect copy() {
return new ChainerDementiaMasterEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
UUID cardId = this.getTargetPointer().getFirst(game, source);
new ReturnFromGraveyardToBattlefieldTargetEffect().apply(game, source);
Permanent permanent = game.getPermanent(cardId);
if (permanent != null) {
ContinuousEffectImpl effect = new BecomesColorTargetEffect(ObjectColor.BLACK, Duration.WhileOnBattlefield);
effect.setTargetPointer(new FixedTarget(permanent, game));
game.addEffect(effect, source);
effect = new BecomesSubtypeTargetEffect(Duration.WhileOnBattlefield, new ArrayList<>(Arrays.asList("Nightmare")), false);
effect.setTargetPointer(new FixedTarget(permanent, game));
game.addEffect(effect, source);
}
return true;
}
return false;
}
}

View file

@ -0,0 +1,78 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.urzasdestiny;
import java.util.UUID;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.MageInt;
import mage.abilities.common.DiesTriggeredAbility;
import mage.abilities.effects.common.DestroyTargetEffect;
import mage.cards.CardImpl;
import mage.filter.FilterPermanent;
import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.target.TargetPermanent;
/**
*
* @author BursegSardaukar
*/
public class GoblinMasons extends CardImpl {
private static final FilterPermanent filter = new FilterPermanent("Wall");
static {
filter.add(new SubtypePredicate("Wall"));
}
public GoblinMasons(UUID ownerId) {
super(ownerId, 86, "Goblin Masons", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{1}{R}");
this.expansionSetCode = "UDS";
this.subtype.add("Goblin");
this.power = new MageInt(2);
this.toughness = new MageInt(1);
//When Goblin Masons dies, destroy target Wall
DiesTriggeredAbility ability = new DiesTriggeredAbility(new DestroyTargetEffect(), false);
ability.addTarget(new TargetPermanent(filter));
this.addAbility(ability);
}
public GoblinMasons(final GoblinMasons card) {
super(card);
}
@Override
public GoblinMasons copy() {
return new GoblinMasons(this);
}
}

View file

@ -0,0 +1,98 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.visions;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.filter.FilterCard;
import mage.filter.common.FilterLandPermanent;
import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.game.Game;
import mage.target.common.TargetCardInLibrary;
import mage.target.common.TargetOpponent;
/**
*
* @author emerald000
*/
public class Tithe extends CardImpl {
public Tithe(UUID ownerId) {
super(ownerId, 123, "Tithe", Rarity.RARE, new CardType[]{CardType.INSTANT}, "{W}");
this.expansionSetCode = "VIS";
// Search your library for a Plains card. If target opponent controls more lands than you, you may search your library for an additional Plains card. Reveal those cards and put them into your hand. Then shuffle your library.
this.getSpellAbility().addEffect(new TitheEffect());
this.getSpellAbility().addTarget(new TargetOpponent());
}
public Tithe(final Tithe card) {
super(card);
}
@Override
public Tithe copy() {
return new Tithe(this);
}
}
class TitheEffect extends OneShotEffect {
private static final FilterCard filter = new FilterCard("Plains");
static {
filter.add(new SubtypePredicate("Plains"));
}
TitheEffect() {
super(Outcome.Benefit);
this.staticText = "Search your library for a Plains card. If target opponent controls more lands than you, you may search your library for an additional Plains card. Reveal those cards and put them into your hand. Then shuffle your library";
}
TitheEffect(final TitheEffect effect) {
super(effect);
}
@Override
public TitheEffect copy() {
return new TitheEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
int numYourLands = game.getBattlefield().countAll(new FilterLandPermanent(), source.getControllerId(), game);
int numOpponentLands = game.getBattlefield().countAll(new FilterLandPermanent(), this.getTargetPointer().getFirst(game, source), game);
new SearchLibraryPutInHandEffect(new TargetCardInLibrary(0, (numOpponentLands > numYourLands ? 2 : 1), filter), true).apply(game, source);
return true;
}
}

View file

@ -0,0 +1,118 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package org.mage.test.cards.abilities.activated;
import mage.abilities.common.LicidAbility;
import mage.abilities.costs.mana.ColoredManaCost;
import mage.abilities.keyword.HasteAbility;
import mage.constants.CardType;
import mage.constants.ColoredManaSymbol;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Ignore;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author emerald0000
*/
public class LicidAbilityTest extends CardTestPlayerBase {
/**
* Activate on another creature
*/
@Test
public void BasicUsageTest() {
addCard(Zone.BATTLEFIELD, playerA, "Pillarfield Ox");
// {R}, {T}: Enraging Licid loses this ability and becomes an Aura enchantment with enchant creature. Attach it to target creature. You may pay {R} to end this effect.
// Enchanted creature has haste.
addCard(Zone.BATTLEFIELD, playerA, "Enraging Licid");
addCard(Zone.BATTLEFIELD, playerA, "Mountain");
activateAbility(1, PhaseStep.UPKEEP, playerA, "{R},", "Pillarfield Ox");
setStopAt(1, PhaseStep.PRECOMBAT_MAIN);
execute();
assertAbility(playerA, "Pillarfield Ox", HasteAbility.getInstance(), true);
assertAbility(playerA, "Enraging Licid", new LicidAbility(new ColoredManaCost(ColoredManaSymbol.R), new ColoredManaCost(ColoredManaSymbol.R)), false);
assertType("Enraging Licid", CardType.ENCHANTMENT, true);
assertType("Enraging Licid", CardType.CREATURE, false);
}
/**
* Use special action to remove the continuous effect
*/
@Test
@Ignore("Test player can't activate special actions yet")
public void SpecialActionTest() {
addCard(Zone.BATTLEFIELD, playerA, "Pillarfield Ox");
// {R}, {T}: Enraging Licid loses this ability and becomes an Aura enchantment with enchant creature. Attach it to target creature. You may pay {R} to end this effect.
// Enchanted creature has haste.
addCard(Zone.BATTLEFIELD, playerA, "Enraging Licid");
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
activateAbility(1, PhaseStep.UPKEEP, playerA, "{R},", "Pillarfield Ox");
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{R}: End");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertActionCount(playerA, 0);
assertAbility(playerA, "Pillarfield Ox", HasteAbility.getInstance(), false);
assertAbility(playerA, "Enraging Licid", new LicidAbility(new ColoredManaCost(ColoredManaSymbol.R), new ColoredManaCost(ColoredManaSymbol.R)), true);
assertType("Enraging Licid", CardType.ENCHANTMENT, false);
assertType("Enraging Licid", CardType.CREATURE, true);
}
/**
* Licid should die if enchanted creature dies
*/
@Test
@Ignore("Enraging Licid doesn't die when its enchanted creature dies due to similarity to Bestow")
public void EnchantedCreatureDiesTest() {
addCard(Zone.BATTLEFIELD, playerA, "Pillarfield Ox");
// {R}, {T}: Enraging Licid loses this ability and becomes an Aura enchantment with enchant creature. Attach it to target creature. You may pay {R} to end this effect.
// Enchanted creature has haste.
addCard(Zone.BATTLEFIELD, playerA, "Enraging Licid");
// Destroy target nonblack creature.
addCard(Zone.HAND, playerB, "Doom Blade");
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);
addCard(Zone.BATTLEFIELD, playerB, "Swamp", 2);
activateAbility(1, PhaseStep.UPKEEP, playerA, "{R},", "Pillarfield Ox");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Doom Blade", "Pillarfield Ox");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertGraveyardCount(playerA, 2); // Pillarfield Ox + Enraging Licid
}
}

View file

@ -25,7 +25,6 @@
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package org.mage.test.cards.abilities.keywords;
import mage.constants.PhaseStep;
@ -40,31 +39,31 @@ import org.mage.test.serverside.base.CardTestPlayerBase;
public class ConspireTest extends CardTestPlayerBase {
/**
* 702.77. Conspire
* 702.77a Conspire is a keyword that represents two abilities. The first is a static ability that functions
* while the spell with conspire is on the stack. The second is a triggered ability that functions
* while the spell with conspire is on the stack. Conspire means As an additional cost to cast
* this spell, you may tap two untapped creatures you control that each share a color with it and
* When you cast this spell, if its conspire cost was paid, copy it. If the spell has any targets, you
* may choose new targets for the copy. Paying a spells conspire cost follows the rules for
* paying additional costs in rules 601.2b and 601.2eg.
* 702.77. Conspire 702.77a Conspire is a keyword that represents two
* abilities. The first is a static ability that functions while the spell
* with conspire is on the stack. The second is a triggered ability that
* functions while the spell with conspire is on the stack. Conspire means
* As an additional cost to cast this spell, you may tap two untapped
* creatures you control that each share a color with it and When you cast
* this spell, if its conspire cost was paid, copy it. If the spell has any
* targets, you may choose new targets for the copy. Paying a spells
* conspire cost follows the rules for paying additional costs in rules
* 601.2b and 601.2eg.
*
* 702.77b If a spell has multiple instances of conspire, each is paid separately and triggers based on
* its own payment, not any other instance of conspire
* 702.77b If a spell has multiple instances of conspire, each is paid
* separately and triggers based on its own payment, not any other instance
* of conspire
*
*/
/**
* Burn Trail
* Sorcery, 3R (4)
* Burn Trail deals 3 damage to target creature or player.
* Burn Trail Sorcery, 3R (4) Burn Trail deals 3 damage to target creature
* or player.
*
* Conspire (As you cast this spell, you may tap two untapped creatures you
* control that share a color with it. When you do, copy it and you may
* choose a new target for the copy.)
* Conspire (As you cast this spell, you may tap two untapped creatures you
* control that share a color with it. When you do, copy it and you may
* choose a new target for the copy.)
*
*/
@Test
public void testConspire() {
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4);
@ -72,7 +71,6 @@ public class ConspireTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerA, "Raging Goblin");
addCard(Zone.HAND, playerA, "Burn Trail");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Burn Trail", playerB);
setChoice(playerA, "Yes");
@ -93,7 +91,6 @@ public class ConspireTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerA, "Raging Goblin");
addCard(Zone.HAND, playerA, "Burn Trail");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Burn Trail", playerB);
setChoice(playerA, "No");
@ -107,4 +104,50 @@ public class ConspireTest extends CardTestPlayerBase {
}
@Test
public void testWortTheRaidmother() {
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 7);
// When Wort, the Raidmother enters the battlefield, put two 1/1 red and green Goblin Warrior creature tokens onto the battlefield.
// Each red or green instant or sorcery spell you cast has conspire.
// (As you cast the spell, you may tap two untapped creatures you control that share a color with it. When you do, copy it and you may choose new targets for the copy.)
addCard(Zone.HAND, playerA, "Wort, the Raidmother");
addCard(Zone.HAND, playerA, "Lightning Bolt");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Wort, the Raidmother");// {4}{R/G}{R/G}
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Lightning Bolt", playerB);
setChoice(playerA, "Yes");
setStopAt(1, PhaseStep.END_TURN);
execute();
assertPermanentCount(playerA, "Wort, the Raidmother", 1);
assertGraveyardCount(playerA, "Lightning Bolt", 1);
assertLife(playerB, 14);
}
@Test
public void testWortTheRaidmotherWithConspireSpell() {
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 10);
addCard(Zone.BATTLEFIELD, playerA, "Raging Goblin", 2);
// When Wort, the Raidmother enters the battlefield, put two 1/1 red and green Goblin Warrior creature tokens onto the battlefield.
// Each red or green instant or sorcery spell you cast has conspire.
// (As you cast the spell, you may tap two untapped creatures you control that share a color with it. When you do, copy it and you may choose new targets for the copy.)
addCard(Zone.HAND, playerA, "Wort, the Raidmother");
addCard(Zone.HAND, playerA, "Burn Trail");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Wort, the Raidmother"); // {4}{R/G}{R/G}
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Burn Trail", playerB);
setChoice(playerA, "Yes"); // use Conspire from Burn Trail itself
setChoice(playerA, "Yes"); // use Conspire gained from Wort, the Raidmother
setStopAt(1, PhaseStep.END_TURN);
execute();
assertPermanentCount(playerA, "Wort, the Raidmother", 1);
assertLife(playerB, 11);
assertLife(playerA, 20);
assertGraveyardCount(playerA, "Burn Trail", 1);
}
}

View file

@ -27,7 +27,6 @@
*/
package org.mage.test.cards.control;
import mage.abilities.keyword.HasteAbility;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
@ -37,15 +36,15 @@ import org.mage.test.serverside.base.CardTestPlayerBase;
*
* @author LevelX2
*/
public class ItThatBetraysTest extends CardTestPlayerBase {
/**
* https://github.com/magefree/mage/issues/796
*
* When an opponent sacrifices a fetchland and you have an It That Betrays in play,
* sacrificing the fetchland that comes under your control from its ability returns
* it to play under your control, allowing you to fetch infinite lands.
* When an opponent sacrifices a fetchland and you have an It That Betrays
* in play, sacrificing the fetchland that comes under your control from its
* ability returns it to play under your control, allowing you to fetch
* infinite lands.
*
*/
@Test

View file

@ -0,0 +1,73 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package org.mage.test.cards.control;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author LevelX2
*/
public class WillbreakerTest extends CardTestPlayerBase {
/**
* http://www.slightlymagic.net/forum/viewtopic.php?f=70&t=17664&start=120#p186736
*
* I tried to activate Retribution of the Ancients while I only controlled
* Nantuko Husk and Willbreaker without +1/+1 counters on them. The program
* didn't let me activate the RotA, even though the creature you choose
* doesn't need to have any counters on it (X can be 0, doesn't say
* otherwise on the card and it isn't a target requirement). It asked me to
* pay B, then choose a creature I controlled, which I did... and then
* nothing happened.
*
*/
@Test
public void testRetributionOfTheAncientsZeroCounter() {
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1);
// {B}, Remove X +1/+1 counters from among creatures you control: Target creature gets -X/-X until end of turn.
addCard(Zone.BATTLEFIELD, playerA, "Retribution of the Ancients", 1); // Enchantment {B}
// Whenever a creature an opponent controls becomes the target of a spell or ability you control, gain control of that creature for as long as you control Willbreaker.
addCard(Zone.BATTLEFIELD, playerA, "Willbreaker", 1);
addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion");
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{B},Remove", "Silvercoat Lion");
setChoice(playerA, "X=0");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertPermanentCount(playerA, "Willbreaker", 1);
assertPermanentCount(playerA, "Silvercoat Lion", 1);
}
}

View file

@ -0,0 +1,88 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package org.mage.test.cards.enchantments;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author LevelX2
*/
public class SkullclampTest extends CardTestPlayerBase {
/**
* Skullclamp and the creature it's attached to are destroyed by same
* Pernicious Deed activation. AFAIK Skullclamp should trigger, but it
* doesn't.
*
* 400.7e Abilities of Auras that trigger when the enchanted permanent
* leaves the battlefield can find the new object that Aura became in its
* owners graveyard if it was put into that graveyard at the same time the
* enchanted permanent left the battlefield. It can also find the new object
* that Aura became in its owners graveyard as a result of being put there
* as a state-based action for not being attached to a permanent. (See rule
* 704.5n.)
*
*/
@Test
public void testPerniciousDeed() {
// Equipped creature gets +1/-1.
// Whenever equipped creature dies, draw two cards.
// Equip {1}
addCard(Zone.BATTLEFIELD, playerA, "Skullclamp", 1);
addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion", 1);
addCard(Zone.BATTLEFIELD, playerA, "Pillarfield Ox", 1);
addCard(Zone.BATTLEFIELD, playerA, "Island", 1);
addCard(Zone.BATTLEFIELD, playerB, "Swamp", 2);
// {X}, Sacrifice Pernicious Deed: Destroy each artifact, creature, and enchantment with converted mana cost X or less.
addCard(Zone.BATTLEFIELD, playerB, "Pernicious Deed"); // Enchantment
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Equip", "Silvercoat Lion");
activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerB, "{X},Sacrifice");
setChoice(playerB, "X=2");
setStopAt(1, PhaseStep.END_TURN);
execute();
assertGraveyardCount(playerA, "Skullclamp", 1);
assertGraveyardCount(playerA, "Silvercoat Lion", 1);
assertGraveyardCount(playerB, "Pernicious Deed", 1);
assertPermanentCount(playerA, "Pillarfield Ox", 1);
assertHandCount(playerA, 2);
}
}

View file

@ -370,6 +370,7 @@ public class TestPlayer implements Player {
}
for (Ability ability : computerPlayer.getPlayable(game, true)) {
if (ability.toString().startsWith(groups[0])) {
int bookmark = game.bookmarkState();
Ability newAbility = ability.copy();
if (groups.length > 1 && !groups[1].equals("target=NO_TARGET")) {
if (!addTargets(newAbility, groups, game)) {
@ -377,9 +378,13 @@ public class TestPlayer implements Player {
break;
}
}
computerPlayer.activateAbility((ActivatedAbility) newAbility, game);
actions.remove(action);
return true;
if (computerPlayer.activateAbility((ActivatedAbility) newAbility, game)) {
actions.remove(action);
return true;
} else {
game.restoreState(bookmark, ability.getRule());
}
}
}
} else if (action.getAction().startsWith("manaActivate:")) {

View file

@ -445,20 +445,28 @@ public abstract class AbilityImpl implements Ability {
public boolean activateAlternateOrAdditionalCosts(MageObject sourceObject, boolean noMana, Player controller, Game game) {
boolean alternativeCostisUsed = false;
if (sourceObject != null && !(sourceObject instanceof Permanent) && !(this instanceof FlashbackAbility)) {
for (Ability ability : sourceObject.getAbilities()) {
// if cast for noMana no Alternative costs are allowed
if (!noMana && ability instanceof AlternativeSourceCosts) {
AlternativeSourceCosts alternativeSpellCosts = (AlternativeSourceCosts) ability;
if (alternativeSpellCosts.isAvailable(this, game)) {
if (alternativeSpellCosts.askToActivateAlternativeCosts(this, game)) {
// only one alternative costs may be activated
alternativeCostisUsed = true;
break;
Abilities<Ability> abilities = null;
if (sourceObject instanceof Card) {
abilities = ((Card) sourceObject).getAbilities(game);
} else {
sourceObject.getAbilities();
}
if (abilities != null) {
for (Ability ability : abilities) {
// if cast for noMana no Alternative costs are allowed
if (!noMana && ability instanceof AlternativeSourceCosts) {
AlternativeSourceCosts alternativeSpellCosts = (AlternativeSourceCosts) ability;
if (alternativeSpellCosts.isAvailable(this, game)) {
if (alternativeSpellCosts.askToActivateAlternativeCosts(this, game)) {
// only one alternative costs may be activated
alternativeCostisUsed = true;
break;
}
}
}
}
if (ability instanceof OptionalAdditionalSourceCosts) {
((OptionalAdditionalSourceCosts) ability).addOptionalAdditionalCosts(this, game);
if (ability instanceof OptionalAdditionalSourceCosts) {
((OptionalAdditionalSourceCosts) ability).addOptionalAdditionalCosts(this, game);
}
}
}
// controller specific alternate spell costs

View file

@ -1,14 +1,16 @@
package mage.abilities.common;
import mage.constants.Zone;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.Effect;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.ZoneChangeEvent;
import mage.game.permanent.Permanent;
/**
* "When enchanted/equipped creature dies" triggered ability
*
* @author Loki
*/
public class DiesAttachedTriggeredAbility extends TriggeredAbilityImpl {
@ -30,7 +32,6 @@ public class DiesAttachedTriggeredAbility extends TriggeredAbilityImpl {
this.diesRuleText = diesRuleText;
}
public DiesAttachedTriggeredAbility(final DiesAttachedTriggeredAbility ability) {
super(ability);
this.attachedDescription = ability.attachedDescription;
@ -49,9 +50,21 @@ public class DiesAttachedTriggeredAbility extends TriggeredAbilityImpl {
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (((ZoneChangeEvent)event).isDiesEvent()) {
if (((ZoneChangeEvent) event).isDiesEvent()) {
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
boolean triggered = false;
if (zEvent.getTarget().getAttachments().contains(this.getSourceId())) {
triggered = true;
} else {
// If both (attachment and attached went to graveyard at the same time, the attachemnets can be already removed from the attached object.)
// So check here with the LKI of the enchantment
Permanent attachment = game.getPermanentOrLKIBattlefield(getSourceId());
if (attachment != null && attachment.getAttachedTo().equals(zEvent.getTargetId())
&& attachment.getAttachedToZoneChangeCounter() == zEvent.getTarget().getZoneChangeCounter(game)) {
triggered = true;
}
}
if (triggered) {
for (Effect effect : getEffects()) {
effect.setValue("attachedTo", zEvent.getTarget());
}

View file

@ -39,11 +39,11 @@ import mage.game.Game;
* @author LevelX2
*/
public class OpponentControllsMoreCondition implements Condition {
public class OpponentControlsMoreCondition implements Condition {
private final FilterPermanent filter;
public OpponentControllsMoreCondition(FilterPermanent filter) {
public OpponentControlsMoreCondition(FilterPermanent filter) {
this.filter = filter;
}

View file

@ -157,8 +157,7 @@ public abstract class VariableCostImpl implements Cost, VariableCost {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
xValue = controller.announceXCost(getMinValue(source, game), getMaxValue(source, game),
new StringBuilder("Announce the number of ").append(actionText).toString(),
game, source, this);
"Announce the number of " + actionText, game, source, this);
}
return xValue;
}

View file

@ -84,6 +84,9 @@ public class RemoveCounterCost extends CostImpl {
int countersRemoved = 0;
Player controller = game.getPlayer(controllerId);
if (controller != null) {
if (countersToRemove == 0) { // Can happen when used for X costs where X = 0;
return paid = true;
}
target.clearChosen();
if (target.choose(Outcome.UnboostCreature, controllerId, sourceId, game)) {
for (UUID targetId : target.getTargets()) {

View file

@ -25,7 +25,6 @@
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.abilities.effects.common;
import java.util.UUID;
@ -52,8 +51,9 @@ public class ExileSourceEffect extends OneShotEffect {
/**
*
* @param toUniqueExileZone moves the card to a source object dependant unique exile zone, so another
* effect of the same source object (e.g. Deadeye Navigator) can identify the card
* @param toUniqueExileZone moves the card to a source object dependant
* unique exile zone, so another effect of the same source object (e.g.
* Deadeye Navigator) can identify the card
*/
public ExileSourceEffect(boolean toUniqueExileZone) {
super(Outcome.Exile);
@ -84,7 +84,7 @@ public class ExileSourceEffect extends OneShotEffect {
exileZoneName = sourceObject.getName();
}
Card sourceCard = (Card) sourceObject;
return controller.moveCardToExileWithInfo(sourceCard, exileZoneId, exileZoneName, source.getSourceId(), game, game.getState().getZone(sourceCard.getId()), true);
return controller.moveCardsToExile(sourceCard, source, game, true, exileZoneId, exileZoneName);
}
return true;
}

View file

@ -1,31 +1,30 @@
/*
* 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.
*/
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.abilities.effects.common;
import mage.abilities.Ability;
@ -65,7 +64,7 @@ public class ExileSpellEffect extends OneShotEffect implements MageSingleton {
if (controller != null) {
Card spellCard = game.getStack().getSpell(source.getSourceId()).getCard();
if (spellCard != null) {
controller.moveCardToExileWithInfo(spellCard, null, "", source.getSourceId(), game, Zone.STACK, true);
controller.moveCards(spellCard, null, Zone.EXILED, source, game);
}
return true;
}

View file

@ -0,0 +1,51 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package mage.abilities.effects.common.combat;
import mage.abilities.Ability;
import mage.abilities.effects.RestrictionEffect;
import mage.constants.Duration;
import mage.filter.common.FilterCreaturePermanent;
import mage.game.Game;
import mage.game.permanent.Permanent;
/**
*
* @author LevelX2
*/
public class CantBeBlockedByAllTargetEffect extends RestrictionEffect {
private final FilterCreaturePermanent filterBlockedBy;
public CantBeBlockedByAllTargetEffect(FilterCreaturePermanent filterBlockedBy, Duration duration) {
super(Duration.WhileOnBattlefield);
this.filterBlockedBy = filterBlockedBy;
staticText = "Target creature"
+ " can't be blocked "
+ (filterBlockedBy.getMessage().startsWith("except by") ? "" : "by ")
+ filterBlockedBy.getMessage();
}
public CantBeBlockedByAllTargetEffect(final CantBeBlockedByAllTargetEffect effect) {
super(effect);
this.filterBlockedBy = effect.filterBlockedBy;
}
@Override
public boolean applies(Permanent permanent, Ability source, Game game) {
return getTargetPointer().getTargets(game, source).contains(permanent.getId());
}
@Override
public boolean canBeBlocked(Permanent attacker, Permanent blocker, Ability source, Game game) {
return !filterBlockedBy.match(blocker, source.getSourceId(), source.getControllerId(), game);
}
@Override
public CantBeBlockedByAllTargetEffect copy() {
return new CantBeBlockedByAllTargetEffect(this);
}
}

View file

@ -27,14 +27,16 @@
*/
package mage.abilities.keyword;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.SpellAbility;
import mage.abilities.StaticAbility;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.costs.Cost;
import mage.abilities.costs.Costs;
import mage.abilities.costs.OptionalAdditionalCost;
import mage.abilities.costs.OptionalAdditionalCostImpl;
import mage.abilities.costs.OptionalAdditionalSourceCosts;
import mage.abilities.costs.common.TapTargetCost;
@ -50,48 +52,77 @@ import mage.filter.predicate.permanent.TappedPredicate;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.stack.Spell;
import mage.game.stack.StackObject;
import mage.players.Player;
import mage.target.common.TargetControlledPermanent;
/**
* 702.77. Conspire 702.77a Conspire is a keyword that represents two abilities.
* The first is a static ability that functions while the spell with conspire is
* on the stack. The second is a triggered ability that functions while the
* spell with conspire is on the stack. "Conspire" means "As an additional cost
* to cast this spell, you may tap two untapped creatures you control that each
* share a color with it" and "When you cast this spell, if its conspire cost
* was paid, copy it. If the spell has any targets, you may choose new targets
* for the copy." Paying a spells conspire cost follows the rules for paying
* additional costs in rules 601.2b and 601.2eg. 702.77b If a spell has
* multiple instances of conspire, each is paid separately and triggers based on
* its own payment, not any other instance of conspire. *
/*
* 702.77. Conspire
* 702.77a Conspire is a keyword that represents two abilities.
* The first is a static ability that functions while the spell with conspire is on the stack.
* The second is a triggered ability that functions while the spell with conspire is on the stack.
* "Conspire" means "As an additional cost to cast this spell,
* you may tap two untapped creatures you control that each share a color with it"
* and "When you cast this spell, if its conspire cost was paid, copy it.
* If the spell has any targets, you may choose new targets for the copy."
* Paying a spells conspire cost follows the rules for paying additional costs in rules 601.2b and 601.2eg.
* 702.77b If a spell has multiple instances of conspire, each is paid separately and triggers
* based on its own payment, not any other instance of conspire. *
*
* @author jeffwadsworth heavily based off the replicate keyword by LevelX
*/
public class ConspireAbility extends StaticAbility implements OptionalAdditionalSourceCosts {
private static final String keywordText = "Conspire";
private static final String reminderTextCost = "<i>As you cast this spell, you may tap two untapped creatures you control that share a color with it. When you do, copy it and you may choose a new target for the copy.)</i>";
private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("two untapped creatures you control that share a color with it");
private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creatures you control that share a color with it");
protected static final String CONSPIRE_ACTIVATION_KEY = "ConspireActivation";
static {
filter.add(Predicates.not(new TappedPredicate()));
filter.add(new SharesColorWithSourcePredicate());
}
Cost costConspire = new TapTargetCost(new TargetControlledPermanent(2, 2, filter, true));
OptionalAdditionalCost conspireCost = new OptionalAdditionalCostImpl(keywordText, "-", reminderTextCost, costConspire);
public enum ConspireTargets {
public ConspireAbility(Card card) {
NONE,
ONE,
MORE
}
private UUID conspireId;
private String reminderText;
private OptionalAdditionalCostImpl conspireCost;
/**
* Unique Id for a ConspireAbility but may not change while a continuous
* effect gives Conspire
*
* @param conspireId
* @param conspireTargets controls the content of the reminder text
*/
public ConspireAbility(UUID conspireId, ConspireTargets conspireTargets) {
super(Zone.STACK, null);
setRuleAtTheTop(false);
addSubAbility(new ConspireTriggeredAbility());
this.conspireId = conspireId;
switch (conspireTargets) {
case NONE:
reminderText = "As you cast this spell, you may tap two untapped creatures you control that share a color with it. When you do, copy it.)";
break;
case ONE:
reminderText = "As you cast this spell, you may tap two untapped creatures you control that share a color with it. When you do, copy it and you may choose a new target for the copy.)";
break;
case MORE:
reminderText = "As you cast this spell, you may tap two untapped creatures you control that share a color with it. When you do, copy it and you may choose a new targets for the copy.)";
break;
}
conspireCost = new OptionalAdditionalCostImpl(keywordText, "-", reminderText,
new TapTargetCost(new TargetControlledPermanent(2, 2, filter, true)));
addSubAbility(new ConspireTriggeredAbility(conspireId));
}
public ConspireAbility(final ConspireAbility ability) {
super(ability);
conspireCost = ability.conspireCost;
this.conspireId = ability.conspireId;
this.conspireCost = ability.conspireCost.copy();
this.reminderText = ability.reminderText;
}
@Override
@ -106,18 +137,21 @@ public class ConspireAbility extends StaticAbility implements OptionalAdditional
}
}
@Override
public boolean isActivated() {
if (conspireCost != null) {
return conspireCost.isActivated();
}
return false;
public UUID getConspireId() {
return conspireId;
}
public void resetConspire() {
if (conspireCost != null) {
conspireCost.reset();
@Override
public boolean isActivated() {
throw new UnsupportedOperationException("Use ConspireAbility.isActivated(Ability ability, Game game) method instead!");
}
public boolean isActivated(Ability ability, Game game) {
Set<UUID> activations = (Set<UUID>) game.getState().getValue(CONSPIRE_ACTIVATION_KEY + ability.getId());
if (activations != null) {
return activations.contains(getConspireId());
}
return false;
}
@Override
@ -125,9 +159,9 @@ public class ConspireAbility extends StaticAbility implements OptionalAdditional
if (ability instanceof SpellAbility) {
Player player = game.getPlayer(controllerId);
if (player != null) {
this.resetConspire();
if (player.chooseUse(Outcome.Benefit, new StringBuilder("Pay ").append(conspireCost.getText(false)).append(" ?").toString(), ability, game)) {
conspireCost.activate();
resetConspire(ability, game);
if (player.chooseUse(Outcome.Benefit, "Pay " + conspireCost.getText(false) + " ?", ability, game)) {
activateConspire(ability, game);
for (Iterator it = ((Costs) conspireCost).iterator(); it.hasNext();) {
Cost cost = (Cost) it.next();
ability.getCosts().add(cost.copy());
@ -137,6 +171,22 @@ public class ConspireAbility extends StaticAbility implements OptionalAdditional
}
}
private void activateConspire(Ability ability, Game game) {
Set<UUID> activations = (Set<UUID>) game.getState().getValue(CONSPIRE_ACTIVATION_KEY + ability.getId());
if (activations == null) {
activations = new HashSet<>();
game.getState().setValue(CONSPIRE_ACTIVATION_KEY + ability.getId(), activations);
}
activations.add(getConspireId());
}
private void resetConspire(Ability ability, Game game) {
Set<UUID> activations = (Set<UUID>) game.getState().getValue(CONSPIRE_ACTIVATION_KEY + ability.getId());
if (activations != null) {
activations.remove(getConspireId());
}
}
@Override
public String getRule() {
StringBuilder sb = new StringBuilder();
@ -167,13 +217,17 @@ public class ConspireAbility extends StaticAbility implements OptionalAdditional
class ConspireTriggeredAbility extends TriggeredAbilityImpl {
public ConspireTriggeredAbility() {
private UUID conspireId;
public ConspireTriggeredAbility(UUID conspireId) {
super(Zone.STACK, new ConspireEffect());
this.conspireId = conspireId;
this.setRuleVisible(false);
}
private ConspireTriggeredAbility(final ConspireTriggeredAbility ability) {
super(ability);
this.conspireId = ability.conspireId;
}
@Override
@ -188,20 +242,18 @@ class ConspireTriggeredAbility extends TriggeredAbilityImpl {
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (event.getSourceId().equals(this.sourceId)) {
StackObject spell = game.getStack().getStackObject(this.sourceId);
if (spell instanceof Spell) {
Card card = game.getCard(spell.getSourceId());
if (card != null) {
for (Ability ability : card.getAbilities()) {
if (ability instanceof ConspireAbility) {
if (((ConspireAbility) ability).isActivated()) {
for (Effect effect : this.getEffects()) {
effect.setValue("ConspireSpell", spell);
}
return true;
if (event.getSourceId().equals(getSourceId())) {
Spell spell = game.getStack().getSpell(event.getSourceId());
for (Ability ability : spell.getAbilities(game)) {
if (ability instanceof ConspireAbility
&& ((ConspireAbility) ability).getConspireId().equals(getConspireId())) {
if (((ConspireAbility) ability).isActivated(spell.getSpellAbility(), game)) {
for (Effect effect : this.getEffects()) {
if (effect instanceof ConspireEffect) {
((ConspireEffect) effect).setConspiredSpell(spell);
}
}
return true;
}
}
}
@ -209,52 +261,53 @@ class ConspireTriggeredAbility extends TriggeredAbilityImpl {
return false;
}
public UUID getConspireId() {
return conspireId;
}
@Override
public String getRule() {
return "Conspire: <i>As you cast this spell, you may tap two untapped creatures you control that share a color with it. When you do, copy it and you may choose a new target for the copy.)</i>";
return "When you pay the conspire costs, copy it and you may choose a new target for the copy.";
}
}
class ConspireEffect extends OneShotEffect {
private Spell conspiredSpell;
public ConspireEffect() {
super(Outcome.Copy);
}
public ConspireEffect(final ConspireEffect effect) {
super(effect);
this.conspiredSpell = effect.conspiredSpell;
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
Spell spell = (Spell) this.getValue("ConspireSpell");
if (spell != null) {
Card card = game.getCard(spell.getSourceId());
if (card != null) {
for (Ability ability : card.getAbilities()) {
if (ability instanceof ConspireAbility) {
if (((ConspireAbility) ability).isActivated()) {
((ConspireAbility) ability).resetConspire();
}
}
}
Spell copy = spell.copySpell();
copy.setControllerId(source.getControllerId());
copy.setCopiedSpell(true);
game.getStack().push(copy);
copy.chooseNewTargets(game, source.getControllerId());
if (!game.isSimulation()) {
game.informPlayers(new StringBuilder(controller.getLogName()).append(copy.getActivatedMessage(game)).toString());
}
return true;
if (controller != null && conspiredSpell != null) {
Card card = game.getCard(conspiredSpell.getSourceId());
if (card != null) {
Spell copy = conspiredSpell.copySpell();
copy.setControllerId(source.getControllerId());
copy.setCopiedSpell(true);
game.getStack().push(copy);
copy.chooseNewTargets(game, source.getControllerId());
if (!game.isSimulation()) {
game.informPlayers(controller.getLogName() + copy.getActivatedMessage(game));
}
return true;
}
}
return false;
}
public void setConspiredSpell(Spell conspiredSpell) {
this.conspiredSpell = conspiredSpell;
}
@Override
public ConspireEffect copy() {
return new ConspireEffect(this);

View file

@ -25,8 +25,6 @@
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.abilities.keyword;
import mage.abilities.Ability;
@ -41,6 +39,8 @@ import mage.constants.Outcome;
import mage.constants.TargetController;
import mage.counters.CounterType;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.permanent.Permanent;
import mage.players.Player;
@ -48,8 +48,6 @@ import mage.players.Player;
*
* @author Plopman
*/
public class CumulativeUpkeepAbility extends BeginningOfUpkeepTriggeredAbility {
private Cost cumulativeCost;
@ -83,7 +81,7 @@ public class CumulativeUpkeepAbility extends BeginningOfUpkeepTriggeredAbility {
class CumulativeUpkeepEffect extends OneShotEffect {
private Cost cumulativeCost;
private final Cost cumulativeCost;
CumulativeUpkeepEffect(Cost cumulativeCost) {
super(Outcome.Sacrifice);
@ -95,46 +93,44 @@ class CumulativeUpkeepEffect extends OneShotEffect {
this.cumulativeCost = effect.cumulativeCost.copy();
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
Permanent permanent = game.getPermanent(source.getSourceId());
if (player != null && permanent != null) {
int ageCounter = permanent.getCounters().getCount(CounterType.AGE);
if(cumulativeCost instanceof ManaCost){
ManaCostsImpl totalCost = new ManaCostsImpl();
for(int i = 0 ; i < ageCounter; i++){
if (cumulativeCost instanceof ManaCost) {
ManaCostsImpl totalCost = new ManaCostsImpl<>();
for (int i = 0; i < ageCounter; i++) {
totalCost.add((ManaCost) cumulativeCost.copy());
}
if (player.chooseUse(Outcome.Benefit, "Pay " + totalCost.getText() + "?", source, game)) {
totalCost.clearPaid();
if (totalCost.payOrRollback(source, game, source.getSourceId(), source.getControllerId())){
if (totalCost.payOrRollback(source, game, source.getSourceId(), source.getControllerId())) {
return true;
}
}
game.fireEvent(new GameEvent(EventType.DIDNT_PAY_CUMULATIVE_UPKEEP, permanent.getId(), permanent.getId(), player.getId(), ageCounter, false));
permanent.sacrifice(source.getSourceId(), game);
return true;
}
else{
CostsImpl totalCost = new CostsImpl();
for(int i = 0 ; i < ageCounter; i++){
} else {
CostsImpl<Cost> totalCost = new CostsImpl<>();
for (int i = 0; i < ageCounter; i++) {
totalCost.add(cumulativeCost.copy());
}
if (player.chooseUse(Outcome.Benefit, totalCost.getText() + "?", source, game)) {
totalCost.clearPaid();
int bookmark = game.bookmarkState();
if (totalCost.pay(source, game, source.getSourceId(), source.getControllerId(), false)){
if (totalCost.pay(source, game, source.getSourceId(), source.getControllerId(), false)) {
return true;
}
else{
} else {
game.restoreState(bookmark, source.getRule());
}
}
game.fireEvent(new GameEvent(EventType.DIDNT_PAY_CUMULATIVE_UPKEEP, permanent.getId(), permanent.getId(), player.getId(), ageCounter, false));
permanent.sacrifice(source.getSourceId(), game);
return true;
}
}
return false;
}

View file

@ -63,7 +63,7 @@ public enum CardRepository {
// raise this if db structure was changed
private static final long CARD_DB_VERSION = 41;
// raise this if new cards were added to the server
private static final long CARD_CONTENT_VERSION = 39;
private static final long CARD_CONTENT_VERSION = 40;
private final Random random = new Random();
private Dao<CardInfo, Object> cardDao;

View file

@ -185,6 +185,7 @@ public class GameEvent implements Serializable {
ENCHANT_PLAYER, ENCHANTED_PLAYER,
CAN_TAKE_MULLIGAN,
FLIP_COIN, COIN_FLIPPED, SCRY, FATESEAL,
DIDNT_PAY_CUMULATIVE_UPKEEP,
//permanent events
ENTERS_THE_BATTLEFIELD,
TAP, TAPPED, TAPPED_FOR_MANA,
@ -241,7 +242,6 @@ public class GameEvent implements Serializable {
//combat events
COMBAT_DAMAGE_APPLIED,
SELECTED_ATTACKER, SELECTED_BLOCKER;
}
public GameEvent(EventType type, UUID targetId, UUID sourceId, UUID playerId) {

View file

@ -109,6 +109,8 @@ public interface Permanent extends Card, Controllable {
UUID getAttachedTo();
int getAttachedToZoneChangeCounter();
void attachTo(UUID permanentId, Game game);
boolean addAttachment(UUID permanentId, Game game);

View file

@ -115,6 +115,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
protected Map<String, List<UUID>> connectedCards = new HashMap<>();
protected HashSet<MageObjectReference> dealtDamageByThisTurn;
protected UUID attachedTo;
protected int attachedToZoneChangeCounter;
protected UUID pairedCard;
protected Counters counters;
protected List<Counter> markedDamage;
@ -172,6 +173,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
}
this.counters = permanent.counters.copy();
this.attachedTo = permanent.attachedTo;
this.attachedToZoneChangeCounter = permanent.attachedToZoneChangeCounter;
this.minBlockedBy = permanent.minBlockedBy;
this.maxBlockedBy = permanent.maxBlockedBy;
this.transformed = permanent.transformed;
@ -676,6 +678,11 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
return attachedTo;
}
@Override
public int getAttachedToZoneChangeCounter() {
return attachedToZoneChangeCounter;
}
@Override
public void addConnectedCard(String key, UUID connectedCard) {
if (this.connectedCards.containsKey(key)) {
@ -712,6 +719,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
}
}
this.attachedTo = permanentId;
this.attachedToZoneChangeCounter = game.getState().getZoneChangeCounter(permanentId);
for (Ability ability : this.getAbilities()) {
for (Iterator<Effect> ite = ability.getEffects(game, EffectType.CONTINUOUS).iterator(); ite.hasNext();) {
ContinuousEffect effect = (ContinuousEffect) ite.next();

View file

@ -106,6 +106,7 @@ public abstract class StackObjImpl implements StackObject {
public boolean chooseNewTargets(Game game, UUID targetControllerId, boolean forceChange, boolean onlyOneTarget, FilterPermanent filterNewTarget) {
Player targetController = game.getPlayer(targetControllerId);
if (targetController != null) {
StringBuilder oldTargetDescription = new StringBuilder();
StringBuilder newTargetDescription = new StringBuilder();
// Fused split spells or spells where "Splice on Arcane" was used can have more than one ability
Abilities<Ability> objectAbilities = new AbilitiesImpl<>();
@ -118,6 +119,7 @@ public abstract class StackObjImpl implements StackObject {
// Some spells can have more than one mode
for (UUID modeId : ability.getModes().getSelectedModes()) {
Mode mode = ability.getModes().get(modeId);
oldTargetDescription.append(ability.getTargetDescription(mode.getTargets(), game));
for (Target target : mode.getTargets()) {
Target newTarget = chooseNewTarget(targetController, ability, mode, target, forceChange, filterNewTarget, game);
// clear the old target and copy all targets from new target
@ -131,7 +133,7 @@ public abstract class StackObjImpl implements StackObject {
}
}
if (newTargetDescription.length() > 0 && !game.isSimulation()) {
if (!newTargetDescription.toString().equals(oldTargetDescription.toString()) && !game.isSimulation()) {
game.informPlayers(this.getLogName() + " is now " + newTargetDescription.toString());
}
return true;

View file

@ -1104,7 +1104,7 @@ public abstract class PlayerImpl implements Player, Serializable {
return false;
}
private void restoreState(int bookmark, String text, Game game) {
protected void restoreState(int bookmark, String text, Game game) {
game.restoreState(bookmark, text);
if (storedBookmark >= bookmark) {
resetStoredBookmark(game);

View file

@ -33,6 +33,9 @@ git log 513a574ae98aff3d7820e5411a8e5f2a6506e69c..head --diff-filter=A --name-st
since 1.4.4.v6
git log 7650f53dee0b4d480d2a63befed72b6c8197e752..head --diff-filter=A --name-status | sed -ne "s/^A[^u]Mage.Sets\/src\/mage\/sets\///p" | sort > added_cards.txt
since 1.4.4.v8
git log 8c7dc7b2da3630b6dfec1390854fa2be11631c79..head --diff-filter=A --name-status | sed -ne "s/^A[^u]Mage.Sets\/src\/mage\/sets\///p" | sort > added_cards.txt
3. Copy added_cards.txt to trunk\Utils folder
4. Run script:
> perl extract_in_wiki_format.perl