Merge remote-tracking branch 'upstream/master'

This commit is contained in:
JRHerlehy 2015-02-20 03:34:56 -08:00
commit b5a1d9a950
61 changed files with 3165 additions and 517 deletions

View file

@ -84,10 +84,14 @@ public class GameView implements Serializable {
public GameView(GameState state, Game game, UUID createdForPlayerId, UUID watcherUserId) { public GameView(GameState state, Game game, UUID createdForPlayerId, UUID watcherUserId) {
Player createdForPlayer = null;
this.isPlayer = createdForPlayerId != null; this.isPlayer = createdForPlayerId != null;
this.priorityTime = game.getPriorityTime(); this.priorityTime = game.getPriorityTime();
for (Player player: state.getPlayers().values()) { for (Player player: state.getPlayers().values()) {
players.add(new PlayerView(player, state, game, createdForPlayerId, watcherUserId)); players.add(new PlayerView(player, state, game, createdForPlayerId, watcherUserId));
if (player.getId().equals(createdForPlayerId)) {
createdForPlayer = player;
}
} }
for (StackObject stackObject: state.getStack()) { for (StackObject stackObject: state.getStack()) {
if (stackObject instanceof StackAbility) { if (stackObject instanceof StackAbility) {
@ -161,7 +165,15 @@ public class GameView implements Serializable {
for (CombatGroup combatGroup: state.getCombat().getGroups()) { for (CombatGroup combatGroup: state.getCombat().getGroups()) {
combat.add(new CombatGroupView(combatGroup, game)); combat.add(new CombatGroupView(combatGroup, game));
} }
this.special = state.getSpecialActions().getControlledBy(state.getPriorityPlayerId()).size() > 0; if (isPlayer) {
// has only to be set for active palyer with priority (e.g. pay mana by delve or Quenchable Fire special action)
if (state.getPriorityPlayerId() == createdForPlayerId && createdForPlayer != null) {
this.special = state.getSpecialActions().getControlledBy(state.getPriorityPlayerId(), createdForPlayer.isInPayManaMode()).size() > 0;
}
} else {
this.special = false;
}
CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get("CastSpellLastTurnWatcher"); CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get("CastSpellLastTurnWatcher");
if (watcher != null) { if (watcher != null) {
spellsCastCurrentTurn = watcher.getAmountOfSpellsAllPlayersCastOnCurrentTurn(); spellsCastCurrentTurn = watcher.getAmountOfSpellsAllPlayersCastOnCurrentTurn();

View file

@ -627,6 +627,8 @@ public class HumanPlayer extends PlayerImpl {
playManaAbilities(unpaid, game); playManaAbilities(unpaid, game);
} else if (response.getString() != null && response.getString().equals("special")) { } else if (response.getString() != null && response.getString().equals("special")) {
if (unpaid instanceof ManaCostsImpl) { if (unpaid instanceof ManaCostsImpl) {
specialManaAction(unpaid, game);
// TODO: delve or convoke cards with PhyrexianManaCost won't work together (this combinaton does not exist yet)
ManaCostsImpl<ManaCost> costs = (ManaCostsImpl<ManaCost>) unpaid; ManaCostsImpl<ManaCost> costs = (ManaCostsImpl<ManaCost>) unpaid;
for (ManaCost cost : costs.getUnpaid()) { for (ManaCost cost : costs.getUnpaid()) {
if (cost instanceof PhyrexianManaCost) { if (cost instanceof PhyrexianManaCost) {
@ -971,8 +973,9 @@ public class HumanPlayer extends PlayerImpl {
} }
protected void specialAction(Game game) { protected void specialAction(Game game) {
LinkedHashMap<UUID, SpecialAction> specialActions = game.getState().getSpecialActions().getControlledBy(playerId, false);
if (!specialActions.isEmpty()) {
updateGameStatePriority("specialAction", game); updateGameStatePriority("specialAction", game);
LinkedHashMap<UUID, SpecialAction> specialActions = game.getState().getSpecialActions().getControlledBy(playerId);
game.fireGetChoiceEvent(playerId, name, null, new ArrayList<>(specialActions.values())); game.fireGetChoiceEvent(playerId, name, null, new ArrayList<>(specialActions.values()));
waitForResponse(game); waitForResponse(game);
if (response.getUUID() != null) { if (response.getUUID() != null) {
@ -981,6 +984,25 @@ public class HumanPlayer extends PlayerImpl {
} }
} }
} }
}
protected void specialManaAction(ManaCost unpaid, Game game) {
LinkedHashMap<UUID, SpecialAction> specialActions = game.getState().getSpecialActions().getControlledBy(playerId, true);
if (!specialActions.isEmpty()) {
updateGameStatePriority("specialAction", game);
game.fireGetChoiceEvent(playerId, name, null, new ArrayList<>(specialActions.values()));
waitForResponse(game);
if (response.getUUID() != null) {
if (specialActions.containsKey(response.getUUID())) {
SpecialAction specialAction = specialActions.get(response.getUUID());
if (specialAction != null) {
specialAction.setUnpaidMana(unpaid);
activateAbility(specialActions.get(response.getUUID()), game);
}
}
}
}
}
protected void activateAbility(LinkedHashMap<UUID, ? extends ActivatedAbility> abilities, MageObject object, Game game) { protected void activateAbility(LinkedHashMap<UUID, ? extends ActivatedAbility> abilities, MageObject object, Game game) {
updateGameStatePriority("activateAbility", game); updateGameStatePriority("activateAbility", game);

View file

@ -28,13 +28,13 @@
package mage.sets.apocalypse; package mage.sets.apocalypse;
import java.util.UUID; import java.util.UUID;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.MageInt; import mage.MageInt;
import mage.abilities.common.DiesTriggeredAbility; import mage.abilities.common.DiesTriggeredAbility;
import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.keyword.TrampleAbility; import mage.abilities.keyword.TrampleAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.game.permanent.token.Token; import mage.game.permanent.token.Token;
/** /**
@ -47,10 +47,14 @@ public class PenumbraWurm extends CardImpl {
super(ownerId, 84, "Penumbra Wurm", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{5}{G}{G}"); super(ownerId, 84, "Penumbra Wurm", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{5}{G}{G}");
this.expansionSetCode = "APC"; this.expansionSetCode = "APC";
this.subtype.add("Wurm"); this.subtype.add("Wurm");
this.color.setGreen(true);
this.power = new MageInt(6); this.power = new MageInt(6);
this.toughness = new MageInt(6); this.toughness = new MageInt(6);
// Trample
this.addAbility(TrampleAbility.getInstance()); this.addAbility(TrampleAbility.getInstance());
// When Penumbra Wurm dies, put a 6/6 black Wurm creature token with trample onto the battlefield.
this.addAbility(new DiesTriggeredAbility(new CreateTokenEffect(new PenumbraWurmToken(), 1), false)); this.addAbility(new DiesTriggeredAbility(new CreateTokenEffect(new PenumbraWurmToken(), 1), false));
} }
@ -70,8 +74,9 @@ class PenumbraWurmToken extends Token {
cardType.add(CardType.CREATURE); cardType.add(CardType.CREATURE);
color.setBlack(true); color.setBlack(true);
subtype.add("Wurm"); subtype.add("Wurm");
power = new MageInt(3); power = new MageInt(6);
toughness = new MageInt(3); toughness = new MageInt(6);
this.addAbility(TrampleAbility.getInstance()); this.addAbility(TrampleAbility.getInstance());
} }
} }

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.coldsnap;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
import mage.abilities.common.DiesAndDealtDamageThisTurnTriggeredAbility;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.HasteAbility;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.counters.CounterType;
/**
*
* @author fireshoes
*/
public class GarzaZolPlagueQueen extends CardImpl {
public GarzaZolPlagueQueen(UUID ownerId) {
super(ownerId, 129, "Garza Zol, Plague Queen", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{4}{U}{B}{R}");
this.expansionSetCode = "CSP";
this.supertype.add("Legendary");
this.subtype.add("Vampire");
this.power = new MageInt(5);
this.toughness = new MageInt(5);
// Flying
this.addAbility(FlyingAbility.getInstance());
// Haste
this.addAbility(HasteAbility.getInstance());
// Whenever a creature dealt damage by Garza Zol, Plague Queen this turn dies, put a +1/+1 counter on Garza Zol.
this.addAbility(new DiesAndDealtDamageThisTurnTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance())));
// Whenever Garza Zol deals combat damage to a player, you may draw a card.
this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new DrawCardSourceControllerEffect(1), true));
}
public GarzaZolPlagueQueen(final GarzaZolPlagueQueen card) {
super(card);
}
@Override
public GarzaZolPlagueQueen copy() {
return new GarzaZolPlagueQueen(this);
}
}

View file

@ -56,7 +56,9 @@ public class QuenchableFire extends CardImpl {
public QuenchableFire(UUID ownerId) { public QuenchableFire(UUID ownerId) {
super(ownerId, 70, "Quenchable Fire", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{3}{R}"); super(ownerId, 70, "Quenchable Fire", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{3}{R}");
this.expansionSetCode = "CON"; this.expansionSetCode = "CON";
this.color.setRed(true);
// Quenchable Fire deals 3 damage to target player.
// It deals an additional 3 damage to that player at the beginning of your next upkeep step unless he or she pays {U} before that step.
this.getSpellAbility().addTarget(new TargetPlayer()); this.getSpellAbility().addTarget(new TargetPlayer());
this.getSpellAbility().addEffect(new DamageTargetEffect(3)); this.getSpellAbility().addEffect(new DamageTargetEffect(3));
this.getSpellAbility().addEffect(new QuenchableFireEffect()); this.getSpellAbility().addEffect(new QuenchableFireEffect());
@ -97,6 +99,7 @@ class QuenchableFireEffect extends OneShotEffect {
delayedAbility.setSourceObject(source.getSourceObject(game)); delayedAbility.setSourceObject(source.getSourceObject(game));
delayedAbility.getTargets().addAll(source.getTargets()); delayedAbility.getTargets().addAll(source.getTargets());
game.addDelayedTriggeredAbility(delayedAbility); game.addDelayedTriggeredAbility(delayedAbility);
//create special action //create special action
QuenchableFireSpecialAction newAction = new QuenchableFireSpecialAction(delayedAbility.getId()); QuenchableFireSpecialAction newAction = new QuenchableFireSpecialAction(delayedAbility.getId());
delayedAbility.setSpecialActionId(newAction.getId()); delayedAbility.setSpecialActionId(newAction.getId());
@ -149,6 +152,7 @@ class QuenchableFireDelayedTriggeredAbility extends DelayedTriggeredAbility {
class QuenchableFireSpecialAction extends SpecialAction { class QuenchableFireSpecialAction extends SpecialAction {
public QuenchableFireSpecialAction(UUID effectId) { public QuenchableFireSpecialAction(UUID effectId) {
super();
this.addCost(new ManaCostsImpl("{U}")); this.addCost(new ManaCostsImpl("{U}"));
this.addEffect(new RemoveDelayedTriggeredAbilityEffect(effectId)); this.addEffect(new RemoveDelayedTriggeredAbilityEffect(effectId));
this.addEffect(new RemoveSpecialActionEffect(this.getId())); this.addEffect(new RemoveSpecialActionEffect(this.getId()));

View file

@ -33,9 +33,10 @@ import java.util.UUID;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Rarity; import mage.constants.Rarity;
import mage.Mana; import mage.Mana;
import mage.abilities.effects.common.BasicManaEffect; import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.mana.BasicManaAbility; import mage.abilities.mana.SimpleManaAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.constants.Zone;
/** /**
* *
@ -46,7 +47,9 @@ public class UrGolemsEye extends CardImpl {
public UrGolemsEye (UUID ownerId) { public UrGolemsEye (UUID ownerId) {
super(ownerId, 155, "Ur-Golem's Eye", Rarity.COMMON, new CardType[]{CardType.ARTIFACT}, "{4}"); super(ownerId, 155, "Ur-Golem's Eye", Rarity.COMMON, new CardType[]{CardType.ARTIFACT}, "{4}");
this.expansionSetCode = "DST"; this.expansionSetCode = "DST";
this.addAbility(new UrGolemsEyeAbility());
// {tap}: Add {2} to your mana pool.
this.addAbility(new SimpleManaAbility(Zone.BATTLEFIELD, new Mana(0,0,0,0,0,2,0), new TapSourceCost()));
} }
public UrGolemsEye (final UrGolemsEye card) { public UrGolemsEye (final UrGolemsEye card) {
@ -60,20 +63,3 @@ public class UrGolemsEye extends CardImpl {
} }
class UrGolemsEyeAbility extends BasicManaAbility {
public UrGolemsEyeAbility() {
super(new BasicManaEffect(new Mana(0, 0, 0, 0, 0, 2, 0)));
this.netMana.add(new Mana(0, 0, 0, 0, 0, 2, 0));
}
public UrGolemsEyeAbility(final UrGolemsEyeAbility ability) {
super(ability);
}
@Override
public UrGolemsEyeAbility copy() {
return new UrGolemsEyeAbility(this);
}
}

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.dissension;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.RegenerateTargetEffect;
import mage.abilities.keyword.GraftAbility;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.counters.CounterType;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.permanent.CounterPredicate;
import mage.target.common.TargetCreaturePermanent;
/**
*
* @author fireshoes
*/
public class SporebackTroll extends CardImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("a creature with a +1/+1 counter on it");
static {
filter.add(new CounterPredicate(CounterType.P1P1));
}
public SporebackTroll(UUID ownerId) {
super(ownerId, 94, "Sporeback Troll", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{3}{G}");
this.expansionSetCode = "DIS";
this.subtype.add("Troll");
this.subtype.add("Mutant");
this.power = new MageInt(0);
this.toughness = new MageInt(0);
// Graft 2
this.addAbility(new GraftAbility(this, 2));
// {1}{G}: Regenerate target creature with a +1/+1 counter on it.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new RegenerateTargetEffect(), new ManaCostsImpl("{1}{G}"));
ability.addTarget(new TargetCreaturePermanent(filter));
this.addAbility(ability);
}
public SporebackTroll(final SporebackTroll card) {
super(card);
}
@Override
public SporebackTroll copy() {
return new SporebackTroll(this);
}
}

View file

@ -89,7 +89,7 @@ public class FrontierSiege extends CardImpl {
Ability ability2 = new ConditionalTriggeredAbility( Ability ability2 = new ConditionalTriggeredAbility(
new EntersBattlefieldControlledTriggeredAbility(Zone.BATTLEFIELD, new FrontierSiegeFightEffect(), filter, true, SetTargetPointer.PERMANENT, ""), new EntersBattlefieldControlledTriggeredAbility(Zone.BATTLEFIELD, new FrontierSiegeFightEffect(), filter, true, SetTargetPointer.PERMANENT, ""),
new ModeChoiceSourceCondition("Dragons"), new ModeChoiceSourceCondition("Dragons"),
ruleTrigger2); ruleTrigger2, true);
ability2.addTarget(new TargetCreaturePermanent(filter2)); ability2.addTarget(new TargetCreaturePermanent(filter2));
this.addAbility(ability2); this.addAbility(ability2);

View file

@ -32,10 +32,8 @@ import java.util.Collections;
import java.util.UUID; import java.util.UUID;
import mage.MageObjectReference; import mage.MageObjectReference;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.costs.mana.ManaCost;
import mage.abilities.costs.mana.ManaCosts; import mage.abilities.costs.mana.ManaCosts;
import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.continious.BecomesFaceDownCreatureEffect; import mage.abilities.effects.common.continious.BecomesFaceDownCreatureEffect;
import mage.abilities.effects.common.continious.BecomesFaceDownCreatureEffect.FaceDownType; import mage.abilities.effects.common.continious.BecomesFaceDownCreatureEffect.FaceDownType;
@ -48,11 +46,8 @@ import mage.constants.Rarity;
import mage.constants.Zone; import mage.constants.Zone;
import mage.filter.common.FilterCreatureCard; import mage.filter.common.FilterCreatureCard;
import mage.game.Game; import mage.game.Game;
import mage.game.events.ZoneChangeEvent;
import mage.game.permanent.PermanentCard;
import mage.players.Player; import mage.players.Player;
import mage.target.TargetPlayer; import mage.target.TargetPlayer;
import mage.target.targetpointer.FixedTarget;
/** /**
* *

View file

@ -32,6 +32,7 @@ import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.ContinuousEffectImpl;
@ -59,6 +60,7 @@ import mage.constants.SubLayer;
import mage.constants.Zone; import mage.constants.Zone;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.util.CardUtil;
/** /**
* *
@ -95,10 +97,11 @@ public class Soulflayer extends CardImpl {
class SoulflayerEffect extends ContinuousEffectImpl implements SourceEffect { class SoulflayerEffect extends ContinuousEffectImpl implements SourceEffect {
private Set<Ability> abilitiesToAdd; private Set<Ability> abilitiesToAdd;
private MageObjectReference objectReference = null;
public SoulflayerEffect() { public SoulflayerEffect() {
super(Duration.WhileOnBattlefield, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility); super(Duration.WhileOnBattlefield, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility);
staticText = "If a creature card with flying was exiled with Soulflayer's delve ability, Soulflayer has flying. The same is true for first strike, double strike, deathtouch, haste, hexproof, indestructible, lifelink, reach, trample, and vigilance"; staticText = "If a creature card with flying was exiled with {this}'s delve ability, {this} has flying. The same is true for first strike, double strike, deathtouch, haste, hexproof, indestructible, lifelink, reach, trample, and vigilance";
abilitiesToAdd = null; abilitiesToAdd = null;
} }
@ -108,6 +111,7 @@ class SoulflayerEffect extends ContinuousEffectImpl implements SourceEffect {
this.abilitiesToAdd = new HashSet<>(); this.abilitiesToAdd = new HashSet<>();
this.abilitiesToAdd.addAll(effect.abilitiesToAdd); this.abilitiesToAdd.addAll(effect.abilitiesToAdd);
} }
this.objectReference = effect.objectReference;
} }
@Override @Override
@ -119,11 +123,11 @@ class SoulflayerEffect extends ContinuousEffectImpl implements SourceEffect {
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(source.getSourceId()); Permanent permanent = game.getPermanent(source.getSourceId());
if (permanent != null) { if (permanent != null) {
if (abilitiesToAdd == null) { if (objectReference == null || !objectReference.refersTo(permanent)) {
for (Ability ability :permanent.getAbilities()) {
if (ability instanceof DelveAbility) {
List<Card> delvedCards = ((DelveAbility) ability).getDelvedCards();
abilitiesToAdd = new HashSet<>(); abilitiesToAdd = new HashSet<>();
this.objectReference = new MageObjectReference(permanent);
String keyString = CardUtil.getCardZoneString("delvedCards", source.getSourceId(), game, true);
List<Card> delvedCards = (List<Card>) game.getState().getValue(keyString);
if (delvedCards != null) { if (delvedCards != null) {
for(Card card: delvedCards) { for(Card card: delvedCards) {
if (!card.getCardType().contains(CardType.CREATURE)) { if (!card.getCardType().contains(CardType.CREATURE)) {
@ -167,8 +171,6 @@ class SoulflayerEffect extends ContinuousEffectImpl implements SourceEffect {
} }
} }
} }
}
}
for (Ability ability: abilitiesToAdd) { for (Ability ability: abilitiesToAdd) {
permanent.addAbility(ability, source.getSourceId(), game); permanent.addAbility(ability, source.getSourceId(), game);
} }

View file

@ -64,7 +64,7 @@ public class ValorousStance extends CardImpl {
this.getSpellAbility().addTarget(new TargetCreaturePermanent()); this.getSpellAbility().addTarget(new TargetCreaturePermanent());
// or destroy target creature with toughness 4 or greater. // or destroy target creature with toughness 4 or greater.
Mode mode1 = new Mode(); Mode mode1 = new Mode();
mode1.getEffects().add(new DestroyTargetEffect(true)); mode1.getEffects().add(new DestroyTargetEffect());
mode1.getTargets().add(new TargetCreaturePermanent(filter)); mode1.getTargets().add(new TargetCreaturePermanent(filter));
this.getSpellAbility().addMode(mode1); this.getSpellAbility().addMode(mode1);

View file

@ -0,0 +1,65 @@
/*
* 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.sets.fifthdawn;
import java.util.UUID;
import mage.constants.*;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.cards.CardImpl;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.abilities.effects.ContinuousRuleModifiyingEffectImpl;
import mage.players.Player;
/**
*
* @author nick.myers
*/
public class EonHub extends CardImpl {
public EonHub(UUID ownerId) {
super(ownerId, 120, "Eon Hub", Rarity.RARE, new CardType[]{CardType.ARTIFACT}, "{5}");
this.expansionSetCode = "5DN";
// Players skip their upkeep steps.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SkipUpkeepStepEffect()));
}
public EonHub(final EonHub card) {
super(card);
}
@Override
public EonHub copy() {
return new EonHub(this);
}
}
class SkipUpkeepStepEffect extends ContinuousRuleModifiyingEffectImpl {
public SkipUpkeepStepEffect() {
super(Duration.WhileOnBattlefield, Outcome.Neutral, false, false);
staticText = "Players skip their upkeep steps";
}
public SkipUpkeepStepEffect(final SkipUpkeepStepEffect effect) {
super(effect);
}
@Override
public SkipUpkeepStepEffect copy() {
return new SkipUpkeepStepEffect(this);
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
Player controller = game.getPlayer(source.getControllerId());
return event.getType() == EventType.UPKEEP_STEP && controller != null && controller.getInRange().contains(event.getPlayerId());
}
}

View file

@ -0,0 +1,62 @@
/*
* 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.futuresight;
import java.util.UUID;
import mage.abilities.effects.keyword.ScryEffect;
import mage.abilities.keyword.BuybackAbility;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Rarity;
/**
*
* @author fireshoes
*/
public class MysticSpeculation extends CardImpl {
public MysticSpeculation(UUID ownerId) {
super(ownerId, 41, "Mystic Speculation", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{U}");
this.expansionSetCode = "FUT";
// Buyback {2}
this.addAbility(new BuybackAbility("{2}"));
// Scry 3.
this.getSpellAbility().addEffect(new ScryEffect(3));
}
public MysticSpeculation(final MysticSpeculation card) {
super(card);
}
@Override
public MysticSpeculation copy() {
return new MysticSpeculation(this);
}
}

View file

@ -0,0 +1,115 @@
/*
* 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.invasion;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DoIfCostPaid;
import mage.abilities.effects.common.GainLifeEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.choices.ChoiceColor;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.filter.FilterPermanent;
import mage.filter.predicate.mageobject.ColorPredicate;
import mage.game.Game;
import mage.players.Player;
/**
*
* @author fireshoes
*/
public class TrevaTheRenewer extends CardImpl {
public TrevaTheRenewer(UUID ownerId) {
super(ownerId, 280, "Treva, the Renewer", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{3}{G}{W}{U}");
this.expansionSetCode = "INV";
this.supertype.add("Legendary");
this.subtype.add("Dragon");
this.power = new MageInt(6);
this.toughness = new MageInt(6);
// Flying
this.addAbility(FlyingAbility.getInstance());
// Whenever Treva, the Renewer deals combat damage to a player, you may pay {2}{W}. If you do, choose a color, then you gain 1 life for each permanent of that color.
this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new DoIfCostPaid(new TrevaTheRenewerEffect(), new ManaCostsImpl("{2}{W}")), false));
}
public TrevaTheRenewer(final TrevaTheRenewer card) {
super(card);
}
@Override
public TrevaTheRenewer copy() {
return new TrevaTheRenewer(this);
}
}
class TrevaTheRenewerEffect extends OneShotEffect {
public TrevaTheRenewerEffect() {
super(Outcome.Benefit);
this.staticText = "choose a color, then you gain 1 life for each permanent of that color.";
}
public TrevaTheRenewerEffect(final TrevaTheRenewerEffect effect) {
super(effect);
}
@Override
public TrevaTheRenewerEffect copy() {
return new TrevaTheRenewerEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller == null) {
return false;
}
ChoiceColor choice = new ChoiceColor();
controller.choose(outcome, choice, game);
if (choice.getColor() != null) {
game.informPlayers(new StringBuilder(controller.getName()).append(" chooses ").append(choice.getColor()).toString());
FilterPermanent filter = new FilterPermanent();
filter.add(new ColorPredicate(choice.getColor()));
int cardsWithColor = game.getBattlefield().count(filter, source.getSourceId(), controller.getId(), game);
if (cardsWithColor > 0) {
new GainLifeEffect(cardsWithColor).apply(game, source);
}
return true;
}
return false;
}
}

View file

@ -34,6 +34,7 @@ import mage.abilities.common.DealsCombatDamageToACreatureTriggeredAbility;
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
import mage.abilities.common.delayed.AtTheEndOfCombatDelayedTriggeredAbility; import mage.abilities.common.delayed.AtTheEndOfCombatDelayedTriggeredAbility;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.effects.common.DestroyTargetEffect;
import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
@ -56,14 +57,18 @@ public class OhranViper extends CardImpl {
this.supertype.add("Snow"); this.supertype.add("Snow");
this.subtype.add("Snake"); this.subtype.add("Snake");
this.color.setGreen(true);
this.power = new MageInt(1); this.power = new MageInt(1);
this.toughness = new MageInt(3); this.toughness = new MageInt(3);
// Whenever Ohran Viper deals combat damage to a creature, destroy that creature at end of combat. // Whenever Ohran Viper deals combat damage to a creature, destroy that creature at end of combat.
this.addAbility(new DealsCombatDamageToACreatureTriggeredAbility(new OhranViperDestroyEffect(), false, true)); this.addAbility(new DealsCombatDamageToACreatureTriggeredAbility(
new CreateDelayedTriggeredAbilityEffect(
new AtTheEndOfCombatDelayedTriggeredAbility(new DestroyTargetEffect("destroy that creature at end of combat")), true),
false,
true));
// Whenever Ohran Viper deals combat damage to a player, you may draw a card. // Whenever Ohran Viper deals combat damage to a player, you may draw a card.
this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new DrawCardSourceControllerEffect(1), false)); this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new DrawCardSourceControllerEffect(1), true));
} }
public OhranViper(final OhranViper card) { public OhranViper(final OhranViper card) {
@ -75,35 +80,3 @@ public class OhranViper extends CardImpl {
return new OhranViper(this); return new OhranViper(this);
} }
} }
class OhranViperDestroyEffect extends OneShotEffect {
OhranViperDestroyEffect() {
super(Outcome.DestroyPermanent);
staticText = "destroy that creature at end of combat";
}
OhranViperDestroyEffect(final OhranViperDestroyEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent targetCreature = game.getPermanent(this.getTargetPointer().getFirst(game, source));
if (targetCreature != null) {
AtTheEndOfCombatDelayedTriggeredAbility delayedAbility = new AtTheEndOfCombatDelayedTriggeredAbility(new DestroyTargetEffect());
delayedAbility.setSourceId(source.getSourceId());
delayedAbility.setControllerId(source.getControllerId());
delayedAbility.setSourceObject(source.getSourceObject(game));
delayedAbility.getEffects().get(0).setTargetPointer(new FixedTarget(targetCreature.getId()));
game.addDelayedTriggeredAbility(delayedAbility);
return true;
}
return false;
}
@Override
public OhranViperDestroyEffect copy() {
return new OhranViperDestroyEffect(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.legends;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.effects.common.continious.SetPowerToughnessSourceEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.filter.common.FilterControlledLandPermanent;
import mage.filter.common.FilterControlledPermanent;
/**
*
* @author fireshoes
*/
public class DakkonBlackblade extends CardImpl {
private static final FilterControlledPermanent filter = new FilterControlledLandPermanent("lands you control");
public DakkonBlackblade(UUID ownerId) {
super(ownerId, 265, "Dakkon Blackblade", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{2}{W}{U}{U}{B}");
this.expansionSetCode = "LEG";
this.supertype.add("Legendary");
this.subtype.add("Human");
this.subtype.add("Warrior");
this.power = new MageInt(0);
this.toughness = new MageInt(0);
// Dakkon Blackblade's power and toughness are each equal to the number of lands you control.
DynamicValue controlledLands = new PermanentsOnBattlefieldCount(filter);
this.addAbility(new SimpleStaticAbility(Zone.ALL, new SetPowerToughnessSourceEffect(controlledLands, Duration.EndOfGame)));
}
public DakkonBlackblade(final DakkonBlackblade card) {
super(card);
}
@Override
public DakkonBlackblade copy() {
return new DakkonBlackblade(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.legends;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.ActivateIfConditionActivatedAbility;
import mage.abilities.condition.common.MyTurnCondition;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.effects.common.discard.DiscardTargetEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.target.TargetPlayer;
/**
*
* @author fireshoes
*/
public class GwendlynDiCorci extends CardImpl {
public GwendlynDiCorci(UUID ownerId) {
super(ownerId, 268, "Gwendlyn Di Corci", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{U}{B}{B}{R}");
this.expansionSetCode = "LEG";
this.supertype.add("Legendary");
this.subtype.add("Human");
this.subtype.add("Rogue");
this.power = new MageInt(3);
this.toughness = new MageInt(5);
// {tap}: Target player discards a card at random. Activate this ability only during your turn.
Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, new DiscardTargetEffect(1, true), new TapSourceCost(), MyTurnCondition.getInstance());
ability.addTarget(new TargetPlayer());
this.addAbility(ability);
}
public GwendlynDiCorci(final GwendlynDiCorci card) {
super(card);
}
@Override
public GwendlynDiCorci copy() {
return new GwendlynDiCorci(this);
}
}

View file

@ -0,0 +1,76 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.legends;
import java.util.UUID;
import mage.MageInt;
import mage.ObjectColor;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.continious.BoostControlledEffect;
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.mageobject.ColorPredicate;
/**
*
* @author fireshoes
*/
public class JacquesLeVert extends CardImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Green creatures");
static {
filter.add(new ColorPredicate(ObjectColor.GREEN));
}
public JacquesLeVert(UUID ownerId) {
super(ownerId, 272, "Jacques le Vert", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{1}{R}{G}{W}");
this.expansionSetCode = "LEG";
this.supertype.add("Legendary");
this.subtype.add("Human");
this.subtype.add("Warrior");
this.power = new MageInt(3);
this.toughness = new MageInt(2);
// Green creatures you control get +0/+2.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostControlledEffect(0,2, Duration.WhileOnBattlefield, filter)));
}
public JacquesLeVert(final JacquesLeVert card) {
super(card);
}
@Override
public JacquesLeVert copy() {
return new JacquesLeVert(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.legends;
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.effects.Effect;
import mage.abilities.effects.common.PreventDamageByTargetEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.target.common.TargetCreaturePermanent;
/**
*
* @author fireshoes
*/
public class LadyEvangela extends CardImpl {
public LadyEvangela(UUID ownerId) {
super(ownerId, 280, "Lady Evangela", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{W}{U}{B}");
this.expansionSetCode = "LEG";
this.supertype.add("Legendary");
this.subtype.add("Human");
this.subtype.add("Cleric");
this.power = new MageInt(1);
this.toughness = new MageInt(2);
// {W}{B}, {tap}: Prevent all combat damage that would be dealt by target creature this turn.
Effect effect = new PreventDamageByTargetEffect(Duration.EndOfTurn, true);
effect.setText("Prevent all combat damage that would be dealt by target creature this turn.");
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl("{W}{B}"));
ability.addEffect(effect);
ability.addCost(new TapSourceCost());
ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability);
}
public LadyEvangela(final LadyEvangela card) {
super(card);
}
@Override
public LadyEvangela copy() {
return new LadyEvangela(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.legends;
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.effects.common.RegenerateTargetEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.target.common.TargetCreaturePermanent;
/**
*
* @author fireshoes
*/
public class Ragnar extends CardImpl {
public Ragnar(UUID ownerId) {
super(ownerId, 290, "Ragnar", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{G}{W}{U}");
this.expansionSetCode = "LEG";
this.supertype.add("Legendary");
this.subtype.add("Human");
this.subtype.add("Cleric");
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// {G}{W}{U}, {tap}: Regenerate target creature.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new RegenerateTargetEffect(), new ManaCostsImpl("{G}{W}{U}"));
ability.addCost(new TapSourceCost());
ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability);
}
public Ragnar(final Ragnar card) {
super(card);
}
@Override
public Ragnar copy() {
return new Ragnar(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.legions;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.TurnedFaceUpSourceTriggeredAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.RegenerateTargetEffect;
import mage.abilities.keyword.MorphAbility;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.target.common.TargetCreaturePermanent;
/**
*
* @author fireshoes
*/
public class DaruMender extends CardImpl {
public DaruMender(UUID ownerId) {
super(ownerId, 8, "Daru Mender", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{W}");
this.expansionSetCode = "LGN";
this.subtype.add("Human");
this.subtype.add("Cleric");
this.power = new MageInt(1);
this.toughness = new MageInt(1);
// Morph {W}
this.addAbility(new MorphAbility(this, new ManaCostsImpl("{W}")));
// When Daru Mender is turned face up, regenerate target creature.
Ability ability = new TurnedFaceUpSourceTriggeredAbility(new RegenerateTargetEffect());
ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability);
}
public DaruMender(final DaruMender card) {
super(card);
}
@Override
public DaruMender copy() {
return new DaruMender(this);
}
}

View file

@ -57,7 +57,7 @@ public class ToxinSliver extends CardImpl {
this.toughness = new MageInt(3); this.toughness = new MageInt(3);
// Whenever a Sliver deals combat damage to a creature, destroy that creature. It can't be regenerated. // Whenever a Sliver deals combat damage to a creature, destroy that creature. It can't be regenerated.
this.addAbility(new DealsDamageToACreatureTriggeredAbility(new DestroyTargetEffect(false), true, false, true)); this.addAbility(new DealsDamageToACreatureTriggeredAbility(new DestroyTargetEffect(true), true, false, true));
} }

View file

@ -28,6 +28,7 @@
package mage.sets.limitedalpha; package mage.sets.limitedalpha;
import java.util.UUID; import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.AsEntersBattlefieldAbility;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
@ -66,8 +67,6 @@ public class PhantasmalTerrain extends CardImpl {
this.expansionSetCode = "LEA"; this.expansionSetCode = "LEA";
this.subtype.add("Aura"); this.subtype.add("Aura");
this.color.setBlue(true);
// Enchant land // Enchant land
TargetPermanent auraTarget = new TargetLandPermanent(); TargetPermanent auraTarget = new TargetLandPermanent();
this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addTarget(auraTarget);
@ -95,7 +94,7 @@ class PhantasmalTerrainChooseEffect extends OneShotEffect {
public PhantasmalTerrainChooseEffect() { public PhantasmalTerrainChooseEffect() {
super(Outcome.Neutral); super(Outcome.Neutral);
this.staticText = "choose a basic land type."; this.staticText = "choose a basic land type";
} }
public PhantasmalTerrainChooseEffect(final PhantasmalTerrainChooseEffect effect) { public PhantasmalTerrainChooseEffect(final PhantasmalTerrainChooseEffect effect) {
@ -109,18 +108,18 @@ class PhantasmalTerrainChooseEffect extends OneShotEffect {
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId()); Player controller = game.getPlayer(source.getControllerId());
if (player != null) { MageObject sourceObject = source.getSourceObject(game);
if (sourceObject != null && controller != null) {
ChoiceImpl choices = new ChoiceImpl(true); ChoiceImpl choices = new ChoiceImpl(true);
choices.setMessage("Choose basic land type"); choices.setMessage("Choose basic land type");
choices.isRequired();
choices.getChoices().add("Forest"); choices.getChoices().add("Forest");
choices.getChoices().add("Plains"); choices.getChoices().add("Plains");
choices.getChoices().add("Mountain"); choices.getChoices().add("Mountain");
choices.getChoices().add("Island"); choices.getChoices().add("Island");
choices.getChoices().add("Swamp"); choices.getChoices().add("Swamp");
if (player.choose(Outcome.Neutral, choices, game)) { if (controller.choose(Outcome.Neutral, choices, game)) {
game.informPlayers(new StringBuilder("Phantasmal Terrain: ").append(" chosen basic land type is ").append(choices.getChoice()).toString()); game.informPlayers(sourceObject.getLogName() + ": chosen basic land type is " + choices.getChoice());
game.getState().setValue(source.getSourceId().toString() + "_PhantasmalTerrain", choices.getChoice()); game.getState().setValue(source.getSourceId().toString() + "_PhantasmalTerrain", choices.getChoice());
return true; return true;
} }
@ -134,7 +133,7 @@ class PhantasmalTerrainContinuousEffect extends ContinuousEffectImpl {
public PhantasmalTerrainContinuousEffect(){ public PhantasmalTerrainContinuousEffect(){
super(Duration.WhileOnBattlefield, Outcome.Neutral); super(Duration.WhileOnBattlefield, Outcome.Neutral);
this.staticText = "Enchanted land is the chosen type."; this.staticText = "enchanted land is the chosen type";
} }
public PhantasmalTerrainContinuousEffect(final PhantasmalTerrainContinuousEffect effect) { public PhantasmalTerrainContinuousEffect(final PhantasmalTerrainContinuousEffect effect) {

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.mercadianmasques;
import java.util.UUID;
import mage.MageInt;
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.RegenerateTargetEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.target.common.TargetCreaturePermanent;
/**
*
* @author fireshoes
*/
public class RushwoodHerbalist extends CardImpl {
public RushwoodHerbalist(UUID ownerId) {
super(ownerId, 265, "Rushwood Herbalist", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{2}{G}");
this.expansionSetCode = "MMQ";
this.subtype.add("Human");
this.subtype.add("Spellshaper");
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// {G}, {tap}, Discard a card: Regenerate target creature.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new RegenerateTargetEffect(), new ManaCostsImpl("{G}"));
ability.addCost(new TapSourceCost());
ability.addCost(new DiscardCardCost());
ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability);
}
public RushwoodHerbalist(final RushwoodHerbalist card) {
super(card);
}
@Override
public RushwoodHerbalist copy() {
return new RushwoodHerbalist(this);
}
}

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.mirage;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.SacrificeTargetCost;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.RegenerateTargetEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.filter.common.FilterControlledLandPermanent;
import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.target.common.TargetControlledPermanent;
import mage.target.common.TargetCreaturePermanent;
/**
*
* @author fireshoes
*/
public class VillageElder extends CardImpl {
private static final FilterControlledLandPermanent filter = new FilterControlledLandPermanent("a Forest");
static{
filter.add(new SubtypePredicate("Forest"));
}
public VillageElder(UUID ownerId) {
super(ownerId, 149, "Village Elder", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{G}");
this.expansionSetCode = "MIR";
this.subtype.add("Human");
this.subtype.add("Druid");
this.power = new MageInt(1);
this.toughness = new MageInt(1);
// {G}, {tap}, Sacrifice a Forest: Regenerate target creature.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new RegenerateTargetEffect(), new ManaCostsImpl("{G}"));
ability.addCost(new TapSourceCost());
ability.addCost(new SacrificeTargetCost(new TargetControlledPermanent(filter)));
ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability);
}
public VillageElder(final VillageElder card) {
super(card);
}
@Override
public VillageElder copy() {
return new VillageElder(this);
}
}

View file

@ -28,6 +28,7 @@
package mage.sets.mirrodinbesieged; package mage.sets.mirrodinbesieged;
import java.util.UUID; import java.util.UUID;
import mage.Mana;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Duration; import mage.constants.Duration;
@ -45,6 +46,7 @@ import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.ContinuousEffectImpl;
import mage.abilities.effects.common.continious.BoostAllEffect; import mage.abilities.effects.common.continious.BoostAllEffect;
import mage.abilities.mana.ColorlessManaAbility; import mage.abilities.mana.ColorlessManaAbility;
import mage.abilities.mana.SimpleManaAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.filter.common.FilterAttackingCreature; import mage.filter.common.FilterAttackingCreature;
import mage.game.Game; import mage.game.Game;
@ -102,13 +104,18 @@ class ContestedWarZoneAbility extends TriggeredAbilityImpl {
return new ContestedWarZoneAbility(this); return new ContestedWarZoneAbility(this);
} }
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DAMAGED_PLAYER;
}
@Override @Override
public boolean checkTrigger(GameEvent event, Game game) { public boolean checkTrigger(GameEvent event, Game game) {
if (event instanceof DamagedPlayerEvent) {
DamagedPlayerEvent damageEvent = (DamagedPlayerEvent)event; DamagedPlayerEvent damageEvent = (DamagedPlayerEvent)event;
Permanent p = game.getPermanent(event.getSourceId()); if (damageEvent.isCombatDamage()) {
if (damageEvent.getPlayerId().equals(controllerId) && damageEvent.isCombatDamage() && p != null && p.getCardType().contains(CardType.CREATURE)) { Permanent permanent = game.getPermanent(event.getSourceId());
game.getState().setValue(sourceId.toString(), p.getControllerId()); if (damageEvent.getPlayerId().equals(getControllerId()) && permanent != null && permanent.getCardType().contains(CardType.CREATURE)) {
game.getState().setValue(getSourceId().toString(), permanent.getControllerId());
return true; return true;
} }
} }

View file

@ -58,7 +58,7 @@ public class FledglingImp extends CardImpl {
// {B}, Discard a card: Fledgling Imp gains flying until end of turn. // {B}, Discard a card: Fledgling Imp gains flying until end of turn.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new GainAbilitySourceEffect(FlyingAbility.getInstance(), Duration.EndOfTurn), new ManaCostsImpl("{B}")); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new GainAbilitySourceEffect(FlyingAbility.getInstance(), Duration.EndOfTurn), new ManaCostsImpl("{B}"));
ability.addCost(new DiscardCardCost(true)); ability.addCost(new DiscardCardCost());
this.addAbility(ability); this.addAbility(ability);
} }

View file

@ -49,7 +49,7 @@ public class CentaurGlade extends CardImpl {
this.expansionSetCode = "ONS"; this.expansionSetCode = "ONS";
// {2}{G}{G}: Put a 3/3 green Centaur creature token onto the battlefield. // {2}{G}{G}: Put a 3/3 green Centaur creature token onto the battlefield.
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new CentaurToken(), 1), new ManaCostsImpl("{3}{G}{G}"))); this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new CentaurToken(), 1), new ManaCostsImpl("{2}{G}{G}")));
} }
public CentaurGlade(final CentaurGlade card) { public CentaurGlade(final CentaurGlade card) {

View file

@ -0,0 +1,54 @@
/*
* 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.phyrexiavsthecoalition;
import java.util.UUID;
import mage.constants.Rarity;
/**
*
* @author anonymous
*/
public class PhyrexianNegator extends mage.sets.urzasdestiny.PhyrexianNegator {
public PhyrexianNegator(UUID ownerId) {
super(ownerId);
this.cardNumber = 1;
this.expansionSetCode = "DDE";
this.rarity = Rarity.MYTHIC;
}
public PhyrexianNegator(final PhyrexianNegator card) {
super(card);
}
@Override
public PhyrexianNegator copy() {
return new PhyrexianNegator(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.phyrexiavsthecoalition;
import java.util.UUID;
/**
*
* @author anonymous
*/
public class TrevaTheRenewer extends mage.sets.invasion.TrevaTheRenewer {
public TrevaTheRenewer(UUID ownerId) {
super(ownerId);
this.cardNumber = 49;
this.expansionSetCode = "DDE";
}
public TrevaTheRenewer(final TrevaTheRenewer card) {
super(card);
}
@Override
public TrevaTheRenewer copy() {
return new TrevaTheRenewer(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.planarchaos;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.DealsDamageToACreatureTriggeredAbility;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.FirstStrikeAbility;
import mage.abilities.keyword.HasteAbility;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.counters.CounterType;
/**
*
* @author fireshoes
*/
public class MirriTheCursed extends CardImpl {
public MirriTheCursed(UUID ownerId) {
super(ownerId, 75, "Mirri the Cursed", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{2}{B}{B}");
this.expansionSetCode = "PLC";
this.supertype.add("Legendary");
this.subtype.add("Vampire");
this.subtype.add("Cat");
this.power = new MageInt(3);
this.toughness = new MageInt(2);
// Flying
this.addAbility(FlyingAbility.getInstance());
// First strike
this.addAbility(FirstStrikeAbility.getInstance());
// Haste
this.addAbility(HasteAbility.getInstance());
// Whenever Mirri the Cursed deals combat damage to a creature, put a +1/+1 counter on Mirri the Cursed.
Ability ability;
ability = new DealsDamageToACreatureTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance(1)), true, false, true);
this.addAbility(ability);
}
public MirriTheCursed(final MirriTheCursed card) {
super(card);
}
@Override
public MirriTheCursed copy() {
return new MirriTheCursed(this);
}
}

View file

@ -0,0 +1,85 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.planeshift;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.SacrificeTargetCost;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.CounterTargetEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.filter.common.FilterControlledPermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.CardTypePredicate;
import mage.target.TargetSpell;
import mage.target.common.TargetControlledPermanent;
/**
*
* @author fireshoes
*/
public class ErtaiTheCorrupted extends CardImpl {
private static final FilterControlledPermanent filter = new FilterControlledPermanent("a creature or enchantment");
static {
filter.add(Predicates.or(new CardTypePredicate(CardType.CREATURE), new CardTypePredicate(CardType.ENCHANTMENT)));
}
public ErtaiTheCorrupted(UUID ownerId) {
super(ownerId, 107, "Ertai, the Corrupted", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{2}{W}{U}{B}");
this.expansionSetCode = "PLS";
this.supertype.add("Legendary");
this.subtype.add("Human");
this.subtype.add("Wizard");
this.power = new MageInt(3);
this.toughness = new MageInt(4);
// {U}, {tap}, Sacrifice a creature or enchantment: Counter target spell.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CounterTargetEffect(), new ManaCostsImpl("{U}"));
ability.addCost(new TapSourceCost());
ability.addCost(new SacrificeTargetCost(new TargetControlledPermanent(filter)));
ability.addTarget(new TargetSpell());
this.addAbility(ability);
}
public ErtaiTheCorrupted(final ErtaiTheCorrupted card) {
super(card);
}
@Override
public ErtaiTheCorrupted copy() {
return new ErtaiTheCorrupted(this);
}
}

View file

@ -0,0 +1,145 @@
/*
* 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.sets.planeshift;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.SearchEffect;
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.Predicates;
import mage.filter.predicate.mageobject.CardTypePredicate;
import mage.game.ExileZone;
import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetCardInLibrary;
import mage.util.CardUtil;
/**
*
* @author nick.myers
*/
public class SkyshipWeatherlight extends CardImpl {
public SkyshipWeatherlight(UUID ownerId) {
super(ownerId, 133, "Skyship Weatherlight", Rarity.RARE, new CardType[]{CardType.ARTIFACT}, "{4}");
this.expansionSetCode = "PLS";
this.supertype.add("Legendary");
// When Skyship Weatherlight enters the battlefield, search your library for any number of artifact and/or creature cards and exile them. Then shuffle your library.
this.addAbility(new EntersBattlefieldTriggeredAbility(new SkyshipWeatherlightEffect(), false));
// {4}, {tap}, Choose a card at random that was removed from the game with Skyship Weatherlight. Put that card into your hand.
SimpleActivatedAbility ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new SkyshipWeatherlightEffect2(), new GenericManaCost(4));
ability.addCost(new TapSourceCost());
this.addAbility(ability);
}
public SkyshipWeatherlight(final SkyshipWeatherlight card) {
super(card);
}
@Override
public SkyshipWeatherlight copy() {
return new SkyshipWeatherlight(this);
}
}
class SkyshipWeatherlightEffect extends SearchEffect {
private static final FilterCard filter = new FilterCard("artifact and/or creature card");
static {
filter.add(Predicates.or(
new CardTypePredicate(CardType.ARTIFACT),
new CardTypePredicate(CardType.CREATURE)));
}
public SkyshipWeatherlightEffect() {
super(new TargetCardInLibrary(0, Integer.MAX_VALUE, filter), Outcome.Neutral);
this.staticText = "search your library for any number of artifact and/or creature cards and remove them from the game. Then shuffle your library";
}
public SkyshipWeatherlightEffect(final SkyshipWeatherlightEffect effect) {
super(effect);
}
@Override
public SkyshipWeatherlightEffect copy() {
return new SkyshipWeatherlightEffect(this);
}
@Override
public boolean apply (Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
MageObject sourceObject = source.getSourceObject(game);
if (sourceObject != null && controller != null) {
if (controller.searchLibrary(target, game)) {
UUID exileZone = CardUtil.getObjectExileZoneId(game, sourceObject);
if (target.getTargets().size() > 0) {
for (UUID cardID : target.getTargets()) {
Card card = controller.getLibrary().getCard(cardID, game);
if (card != null) {
controller.moveCardToExileWithInfo(card, exileZone, sourceObject.getLogName(), source.getSourceId(), game, Zone.LIBRARY);
}
}
}
}
controller.shuffleLibrary(game);
return true;
}
return false;
}
}
class SkyshipWeatherlightEffect2 extends OneShotEffect {
public SkyshipWeatherlightEffect2() {
super(Outcome.ReturnToHand);
this.staticText = "Choose a card at random that was removed from the game with {this}. Put that card into your hand";
}
public SkyshipWeatherlightEffect2(final SkyshipWeatherlightEffect2 effect) {
super(effect);
}
@Override
public SkyshipWeatherlightEffect2 copy() {
return new SkyshipWeatherlightEffect2(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
MageObject sourceObject = source.getSourceObject(game);
if (sourceObject != null && controller != null) {
ExileZone exZone = game.getExile().getExileZone(CardUtil.getObjectExileZoneId(game, sourceObject));
if (exZone != null) {
Card card = exZone.getRandom(game);
controller.moveCardToHandWithInfo(card, source.getSourceId(), game, Zone.EXILED);
}
return true;
}
return false;
}
}

View file

@ -0,0 +1,63 @@
/*
* 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.portalthreekingdoms;
import java.util.UUID;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.discard.DiscardControllerEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Rarity;
/**
*
* @author fireshoes
*/
public class ControlOfTheCourt extends CardImpl {
public ControlOfTheCourt(UUID ownerId) {
super(ownerId, 105, "Control of the Court", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{1}{R}");
this.expansionSetCode = "PTK";
// Draw four cards, then discard three cards at random.
this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(4));
Effect effect = new DiscardControllerEffect(3, true);
effect.setText("then discard three cards at random");
this.getSpellAbility().addEffect(effect);
}
public ControlOfTheCourt(final ControlOfTheCourt card) {
super(card);
}
@Override
public ControlOfTheCourt copy() {
return new ControlOfTheCourt(this);
}
}

View file

@ -27,16 +27,25 @@
*/ */
package mage.sets.scarsofmirrodin; package mage.sets.scarsofmirrodin;
import java.util.*; import java.util.AbstractMap;
import java.util.HashSet;
import mage.abilities.SpecialAction; import java.util.Map;
import mage.abilities.common.SimpleStaticAbility; import java.util.Set;
import mage.abilities.effects.*; import java.util.UUID;
import mage.constants.*;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.SpecialAction;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.ContinuousRuleModifiyingEffectImpl;
import mage.abilities.effects.OneShotEffect;
import mage.cards.CardImpl; 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.constants.Zone;
import mage.game.Game; import mage.game.Game;
import mage.game.events.GameEvent; import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType; import mage.game.events.GameEvent.EventType;
@ -62,6 +71,7 @@ public class LeoninArbiter extends CardImpl {
// Players can't search libraries. // Players can't search libraries.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new LeoninArbiterCantSearchEffect(keyString))); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new LeoninArbiterCantSearchEffect(keyString)));
// Any player may pay {2} for that player to ignore this effect until end of turn. // Any player may pay {2} for that player to ignore this effect until end of turn.
this.addAbility(new LeoninArbiterSpecialAction(keyString)); this.addAbility(new LeoninArbiterSpecialAction(keyString));
} }

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.scourge;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.DrawCardAllEffect;
import mage.abilities.effects.common.discard.DiscardHandAllEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Rarity;
/**
*
* @author fireshoes
*/
public class DragonMage extends CardImpl {
public DragonMage(UUID ownerId) {
super(ownerId, 87, "Dragon Mage", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{5}{R}{R}");
this.expansionSetCode = "SCG";
this.subtype.add("Dragon");
this.subtype.add("Wizard");
this.power = new MageInt(5);
this.toughness = new MageInt(5);
// Flying
this.addAbility(FlyingAbility.getInstance());
// Whenever Dragon Mage deals combat damage to a player, each player discards his or her hand and draws seven cards.
Ability ability = new DealsCombatDamageToAPlayerTriggeredAbility(new DiscardHandAllEffect(), false);
Effect effect = new DrawCardAllEffect(7);
effect.setText("and draws seven cards");
ability.addEffect(effect);
this.addAbility(ability);
}
public DragonMage(final DragonMage card) {
super(card);
}
@Override
public DragonMage copy() {
return new DragonMage(this);
}
}

View file

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

View file

@ -0,0 +1,65 @@
/*
* 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.abilities.effects.common.continious.BoostTargetEffect;
import mage.abilities.keyword.ConspireAbility;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Rarity;
import mage.target.common.TargetCreaturePermanent;
/**
*
* @author jeffwadsworth
*/
public class BarkshellBlessing extends CardImpl {
public BarkshellBlessing(UUID ownerId) {
super(ownerId, 224, "Barkshell Blessing", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{G/W}");
this.expansionSetCode = "SHM";
// Target creature gets +2/+2 until end of turn.
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
this.getSpellAbility().addEffect(new BoostTargetEffect(2, 2, Duration.EndOfTurn));
// Conspire
this.addAbility(new ConspireAbility(this));
}
public BarkshellBlessing(final BarkshellBlessing card) {
super(card);
}
@Override
public BarkshellBlessing copy() {
return new BarkshellBlessing(this);
}
}

View file

@ -0,0 +1,94 @@
/*
* 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.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.ConspireAbility;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.game.Game;
import mage.players.Player;
/**
*
* @author jeffwadsworth
*/
public class GhastlyDiscovery extends CardImpl {
public GhastlyDiscovery(UUID ownerId) {
super(ownerId, 39, "Ghastly Discovery", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{2}{U}");
this.expansionSetCode = "SHM";
// Draw two cards, then discard a card.
this.getSpellAbility().addEffect(new GhastlyDiscoveryEffect());
// Conspire
this.addAbility(new ConspireAbility(this));
}
public GhastlyDiscovery(final GhastlyDiscovery card) {
super(card);
}
@Override
public GhastlyDiscovery copy() {
return new GhastlyDiscovery(this);
}
}
class GhastlyDiscoveryEffect extends OneShotEffect {
public GhastlyDiscoveryEffect() {
super(Outcome.Benefit);
this.staticText = "Draw two cards, then discard a card";
}
public GhastlyDiscoveryEffect(final GhastlyDiscoveryEffect effect) {
super(effect);
}
@Override
public GhastlyDiscoveryEffect copy() {
return new GhastlyDiscoveryEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
controller.drawCards(2, game);
controller.discard(1, false, source, game);
return true;
}
return false;
}
}

View file

@ -0,0 +1,121 @@
/*
* 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.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ExileTargetEffect;
import mage.abilities.keyword.ConspireAbility;
import mage.abilities.keyword.HasteAbility;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.game.Game;
import mage.game.permanent.token.Token;
import mage.target.targetpointer.FixedTarget;
/**
*
* @author jeffwadsworth
*/
public class Giantbaiting extends CardImpl {
public Giantbaiting(UUID ownerId) {
super(ownerId, 207, "Giantbaiting", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{2}{R/G}");
this.expansionSetCode = "SHM";
// Put a 4/4 red and green Giant Warrior creature token with haste onto the battlefield. Exile it at the beginning of the next end step.
this.getSpellAbility().addEffect(new GiantbaitingEffect());
// Conspire
this.addAbility(new ConspireAbility(this));
}
public Giantbaiting(final Giantbaiting card) {
super(card);
}
@Override
public Giantbaiting copy() {
return new Giantbaiting(this);
}
}
class GiantbaitingEffect extends OneShotEffect {
public GiantbaitingEffect() {
super(Outcome.PutCreatureInPlay);
this.staticText = "Put a 4/4 red and green Giant Warrior creature token with haste onto the battlefield. Exile it at the beginning of the next end step";
}
public GiantbaitingEffect(final GiantbaitingEffect effect) {
super(effect);
}
@Override
public GiantbaitingEffect copy() {
return new GiantbaitingEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Token token = new GiantWarriorToken();
if (token.putOntoBattlefield(1, game, source.getSourceId(), source.getControllerId())) {
ExileTargetEffect exileEffect = new ExileTargetEffect();
exileEffect.setTargetPointer(new FixedTarget(token.getLastAddedToken()));
DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(exileEffect);
delayedAbility.setSourceId(source.getSourceId());
delayedAbility.setControllerId(source.getControllerId());
delayedAbility.setSourceObject(source.getSourceObject(game));
game.addDelayedTriggeredAbility(delayedAbility);
return true;
}
return false;
}
}
class GiantWarriorToken extends Token {
GiantWarriorToken() {
super("Giant Warrior", "4/4 red and green Giant Warrior creature token with haste");
cardType.add(CardType.CREATURE);
color.setRed(true);
color.setGreen(true);
subtype.add("Giant");
subtype.add("Warrior");
power = new MageInt(4);
toughness = new MageInt(4);
this.addAbility(HasteAbility.getInstance());
}
}

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.shadowmoor;
import java.util.UUID;
/**
*
* @author jeffwadsworth
*/
public class TorrentOfSouls extends mage.sets.sorinvstibalt.TorrentOfSouls {
public TorrentOfSouls(UUID ownerId) {
super(ownerId);
this.cardNumber = 199;
this.expansionSetCode = "SHM";
}
public TorrentOfSouls(final TorrentOfSouls card) {
super(card);
}
@Override
public TorrentOfSouls copy() {
return new TorrentOfSouls(this);
}
}

View file

@ -0,0 +1,111 @@
/*
* 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.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.ConspireAbility;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.permanent.TappedPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetCreaturePermanent;
/**
*
* @author jeffwadsworth
*/
public class TraitorsRoar extends CardImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("untapped creature");
static {
filter.add(Predicates.not(new TappedPredicate()));
}
public TraitorsRoar(UUID ownerId) {
super(ownerId, 200, "Traitor's Roar", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{4}{B/R}");
this.expansionSetCode = "SHM";
// Tap target untapped creature. It deals damage equal to its power to its controller.
this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter));
this.getSpellAbility().addEffect(new TraitorsRoarEffect());
// Conspire
this.addAbility(new ConspireAbility(this));
}
public TraitorsRoar(final TraitorsRoar card) {
super(card);
}
@Override
public TraitorsRoar copy() {
return new TraitorsRoar(this);
}
}
class TraitorsRoarEffect extends OneShotEffect {
public TraitorsRoarEffect() {
super(Outcome.Detriment);
this.staticText = "Tap target untapped creature. It deals damage equal to its power to its controller";
}
public TraitorsRoarEffect(final TraitorsRoarEffect effect) {
super(effect);
}
@Override
public TraitorsRoarEffect copy() {
return new TraitorsRoarEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
boolean applied = false;
Permanent targetCreature = game.getPermanent(targetPointer.getFirst(game, source));
if (targetCreature != null) {
applied = targetCreature.tap(game);
Player controller = game.getPlayer(targetCreature.getControllerId());
if (controller != null) {
controller.damage(targetCreature.getPower().getValue(), source.getSourceId(), game, false, true);
applied = true;
}
}
return applied;
}
}

View file

@ -0,0 +1,123 @@
/*
* 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.sorinvstibalt;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.condition.common.ManaWasSpentCondition;
import mage.abilities.decorator.ConditionalOneShotEffect;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ReturnToBattlefieldUnderYourControlTargetEffect;
import mage.abilities.effects.common.continious.BoostAllEffect;
import mage.abilities.effects.common.continious.GainAbilityAllEffect;
import mage.abilities.keyword.HasteAbility;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.ColoredManaSymbol;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.filter.common.FilterCreatureCard;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.permanent.ControllerIdPredicate;
import mage.game.Game;
import mage.players.Player;
import mage.target.Target;
import mage.target.TargetPlayer;
import mage.target.common.TargetCardInYourGraveyard;
import mage.watchers.common.ManaSpentToCastWatcher;
/**
*
* @author jeffwadsworth
*/
public class TorrentOfSouls extends CardImpl {
public TorrentOfSouls(UUID ownerId) {
super(ownerId, 71, "Torrent of Souls", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{4}{B/R}");
this.expansionSetCode = "DDK";
// Return up to one target creature card from your graveyard to the battlefield if {B} was spent to cast Torrent of Souls. Creatures target player controls get +2/+0 and gain haste until end of turn if {R} was spent to cast Torrent of Souls.
Target targetCreature = new TargetCardInYourGraveyard(0, 1, new FilterCreatureCard("target creature card in your graveyard"));
Target targetPlayer = new TargetPlayer();
this.getSpellAbility().addEffect(new ConditionalOneShotEffect(
new ReturnToBattlefieldUnderYourControlTargetEffect(),
new ManaWasSpentCondition(ColoredManaSymbol.B), "Return up to one target creature card from your graveyard to the battlefield if {B} was spent to cast {this}"));
this.getSpellAbility().addEffect(new ConditionalOneShotEffect(
new TorrentOfSoulsEffect(),
new ManaWasSpentCondition(ColoredManaSymbol.R), " Creatures target player controls get +2/+0 and gain haste until end of turn if {R} was spent to cast {this}"));
this.getSpellAbility().addTarget(targetCreature);
this.getSpellAbility().addTarget(targetPlayer);
this.addInfo("Info1", "<i>(Do both if {B}{R} was spent.)</i>");
this.addWatcher(new ManaSpentToCastWatcher());
}
public TorrentOfSouls(final TorrentOfSouls card) {
super(card);
}
@Override
public TorrentOfSouls copy() {
return new TorrentOfSouls(this);
}
}
class TorrentOfSoulsEffect extends OneShotEffect {
public TorrentOfSoulsEffect() {
super(Outcome.BoostCreature);
}
public TorrentOfSoulsEffect(final TorrentOfSoulsEffect effect) {
super(effect);
}
@Override
public TorrentOfSoulsEffect copy() {
return new TorrentOfSoulsEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player targetedPlayer = game.getPlayer(source.getTargets().get(1).getFirstTarget());
if (targetedPlayer != null) {
FilterCreaturePermanent filter = new FilterCreaturePermanent();
filter.add(new ControllerIdPredicate(targetedPlayer.getId()));
ContinuousEffect boostEffect = new BoostAllEffect(2, 0, Duration.EndOfTurn, filter, true);
ContinuousEffect gainAbilityEffect = new GainAbilityAllEffect(HasteAbility.getInstance(), Duration.EndOfTurn, filter);
game.addEffect(boostEffect, source);
game.addEffect(gainAbilityEffect, source);
return true;
}
return false;
}
}

View file

@ -0,0 +1,100 @@
/*
* 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.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SkipUntapOptionalAbility;
import mage.abilities.condition.Condition;
import mage.abilities.costs.common.SacrificeTargetCost;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.decorator.ConditionalContinousEffect;
import mage.abilities.effects.common.continious.GainControlTargetEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.common.TargetControlledCreaturePermanent;
import mage.target.common.TargetCreaturePermanent;
/**
*
* @author fireshoes
*/
public class HelmOfPossession extends CardImpl {
public HelmOfPossession(UUID ownerId) {
super(ownerId, 281, "Helm of Possession", Rarity.RARE, new CardType[]{CardType.ARTIFACT}, "{4}");
this.expansionSetCode = "TMP";
// You may choose not to untap Helm of Possession during your untap step.
this.addAbility(new SkipUntapOptionalAbility());
// {2}, {tap}, Sacrifice a creature: Gain control of target creature for as long as you control Helm of Possession and Helm of Possession remains tapped.
ConditionalContinousEffect effect = new ConditionalContinousEffect(
new GainControlTargetEffect(Duration.Custom),
new HelmOfPossessionCondition(),
"Gain control of target creature for as long as you control {this} and {this} remains tapped");
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new TapSourceCost());
ability.addTarget(new TargetCreaturePermanent());
ability.addCost(new SacrificeTargetCost(new TargetControlledCreaturePermanent()));
this.addAbility(ability);
}
public HelmOfPossession(final HelmOfPossession card) {
super(card);
}
@Override
public HelmOfPossession copy() {
return new HelmOfPossession(this);
}
}
class HelmOfPossessionCondition implements Condition {
private UUID controllerId;
@Override
public boolean apply(Game game, Ability source) {
if (controllerId == null) {
controllerId = source.getControllerId();
}
Permanent permanent = game.getBattlefield().getPermanent(source.getSourceId());
if (permanent != null){
if (permanent.isTapped()){
return controllerId == source.getControllerId();
}
}
return false;
}
}

View file

@ -29,15 +29,11 @@ package mage.sets.tenth;
import java.util.UUID; import java.util.UUID;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Rarity; import mage.constants.Rarity;
import mage.abilities.Ability; import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.cards.Card; import mage.abilities.effects.common.discard.DiscardControllerEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.Cards;
import mage.game.Game;
import mage.players.Player;
/** /**
* *
@ -52,8 +48,10 @@ public class GoblinLore extends CardImpl {
this.color.setRed(true); this.color.setRed(true);
// Draw four cards, then discard three cards at random. // Draw four cards, then discard three cards at random.
this.getSpellAbility().addEffect(new GoblinLoreEffect()); this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(4));
} Effect effect = new DiscardControllerEffect(3, true);
effect.setText("then discard three cards at random");
this.getSpellAbility().addEffect(effect); }
public GoblinLore(final GoblinLore card) { public GoblinLore(final GoblinLore card) {
super(card); super(card);
@ -64,37 +62,3 @@ public class GoblinLore extends CardImpl {
return new GoblinLore(this); return new GoblinLore(this);
} }
} }
class GoblinLoreEffect extends OneShotEffect {
public GoblinLoreEffect() {
super(Outcome.DrawCard);
this.staticText = "Draw four cards, then discard three cards at random";
}
public GoblinLoreEffect(final GoblinLoreEffect effect) {
super(effect);
}
@Override
public GoblinLoreEffect copy() {
return new GoblinLoreEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player != null) {
player.drawCards(4, game);
Cards hand = player.getHand();
for (int i = 0; i < 3; i++) {
Card card = hand.getRandom(game);
if (card != null) {
player.discard(card, 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.thedark;
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.effects.common.RegenerateTargetEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.target.common.TargetCreaturePermanent;
/**
*
* @author fireshoes
*/
public class NiallSilvain extends CardImpl {
public NiallSilvain(UUID ownerId) {
super(ownerId, 45, "Niall Silvain", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{G}{G}{G}");
this.expansionSetCode = "DRK";
this.subtype.add("Ouphe");
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// {G}{G}{G}{G}, {tap}: Regenerate target creature.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new RegenerateTargetEffect(), new ManaCostsImpl("{G}{G}{G}{G}"));
ability.addCost(new TapSourceCost());
ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability);
}
public NiallSilvain(final NiallSilvain card) {
super(card);
}
@Override
public NiallSilvain copy() {
return new NiallSilvain(this);
}
}

View file

@ -99,7 +99,10 @@ class NetherTraitorTriggeredAbility extends TriggeredAbilityImpl {
ZoneChangeEvent zEvent = (ZoneChangeEvent) event; ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
if (zEvent.getFromZone() == Zone.BATTLEFIELD && zEvent.getToZone() == Zone.GRAVEYARD) { if (zEvent.getFromZone() == Zone.BATTLEFIELD && zEvent.getToZone() == Zone.GRAVEYARD) {
Card card = game.getCard(event.getTargetId()); Card card = game.getCard(event.getTargetId());
if (card != null && card.getOwnerId().equals(this.getControllerId()) && !card.getId().equals(this.getSourceId())) { if (card != null &&
card.getOwnerId().equals(this.getControllerId()) &&
card.getCardType().contains(CardType.CREATURE)&&
!card.getId().equals(this.getSourceId())) {
return true; return true;
} }
} }

View file

@ -29,15 +29,14 @@ package mage.sets.urzassaga;
import java.util.HashSet; import java.util.HashSet;
import java.util.UUID; import java.util.UUID;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.choices.Choice; import mage.choices.Choice;
import mage.choices.ChoiceImpl; import mage.choices.ChoiceImpl;
import mage.constants.CardType;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.filter.FilterPermanent; import mage.filter.FilterPermanent;
import mage.filter.predicate.Predicates; import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.CardTypePredicate; import mage.filter.predicate.mageobject.CardTypePredicate;
@ -53,13 +52,10 @@ import mage.target.TargetPlayer;
*/ */
public class Turnabout extends CardImpl { public class Turnabout extends CardImpl {
public Turnabout(UUID ownerId) { public Turnabout(UUID ownerId) {
super(ownerId, 105, "Turnabout", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{2}{U}{U}"); super(ownerId, 105, "Turnabout", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{2}{U}{U}");
this.expansionSetCode = "USG"; this.expansionSetCode = "USG";
this.color.setBlue(true);
// Choose artifact, creature, or land. Tap all untapped permanents of the chosen type target player controls, or untap all tapped permanents of that type that player controls. // Choose artifact, creature, or land. Tap all untapped permanents of the chosen type target player controls, or untap all tapped permanents of that type that player controls.
this.getSpellAbility().addTarget(new TargetPlayer()); this.getSpellAbility().addTarget(new TargetPlayer());
this.getSpellAbility().addEffect(new TurnaboutEffect()); this.getSpellAbility().addEffect(new TurnaboutEffect());
@ -78,14 +74,16 @@ public class Turnabout extends CardImpl {
class TurnaboutEffect extends OneShotEffect { class TurnaboutEffect extends OneShotEffect {
private static final HashSet<String> choice = new HashSet<String>(); private static final HashSet<String> choice = new HashSet<>();
static { static {
choice.add(CardType.ARTIFACT.toString()); choice.add(CardType.ARTIFACT.toString());
choice.add(CardType.CREATURE.toString()); choice.add(CardType.CREATURE.toString());
choice.add(CardType.LAND.toString()); choice.add(CardType.LAND.toString());
} }
private static final HashSet<String> choice2 = new HashSet<String>(); private static final HashSet<String> choice2 = new HashSet<>();
static { static {
choice2.add("Untap"); choice2.add("Untap");
choice2.add("Tap"); choice2.add("Tap");
@ -107,12 +105,16 @@ class TurnaboutEffect extends OneShotEffect {
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId()); Player controller = game.getPlayer(source.getControllerId());
UUID target = source.getFirstTarget(); UUID target = source.getFirstTarget();
if(player != null && target != null){ if (controller != null && target != null) {
Choice choiceImpl = new ChoiceImpl(); Choice choiceImpl = new ChoiceImpl();
choiceImpl.setChoices(choice); choiceImpl.setChoices(choice);
while(!player.choose(outcome.Neutral, choiceImpl, game)); while (!controller.choose(Outcome.Neutral, choiceImpl, game)) {
if (!controller.isInGame()) {
return false;
}
}
CardType type; CardType type;
String choosenType = choiceImpl.getChoice(); String choosenType = choiceImpl.getChoice();
@ -126,12 +128,15 @@ class TurnaboutEffect extends OneShotEffect {
choiceImpl = new ChoiceImpl(); choiceImpl = new ChoiceImpl();
choiceImpl.setChoices(choice2); choiceImpl.setChoices(choice2);
while(!player.choose(outcome.Neutral, choiceImpl, game)); while (!controller.choose(Outcome.Neutral, choiceImpl, game)) {
if (!controller.isInGame()) {
return false;
}
}
FilterPermanent filter = new FilterPermanent(); FilterPermanent filter = new FilterPermanent();
filter.add(new CardTypePredicate(type)); filter.add(new CardTypePredicate(type));
if (choiceImpl.getChoice().equals("Untap")) { if (choiceImpl.getChoice().equals("Untap")) {
filter.add(new TappedPredicate()); filter.add(new TappedPredicate());
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) { for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) {
@ -139,8 +144,7 @@ class TurnaboutEffect extends OneShotEffect {
permanent.untap(game); permanent.untap(game);
} }
} }
} } else {
else{
filter.add(Predicates.not(new TappedPredicate())); filter.add(Predicates.not(new TappedPredicate()));
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) { for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) {
if (permanent.getControllerId().equals(target)) { if (permanent.getControllerId().equals(target)) {
@ -149,10 +153,8 @@ class TurnaboutEffect extends OneShotEffect {
} }
} }
} }
return true; return true;
} }
} }

View file

@ -0,0 +1,54 @@
/*
* 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.constants.Rarity;
/**
*
* @author anonymous
*/
public class SisaysRing extends mage.sets.seventhedition.SisaysRing {
public SisaysRing(UUID ownerId) {
super(ownerId);
this.cardNumber = 154;
this.expansionSetCode = "VIS";
this.rarity = Rarity.COMMON;
}
public SisaysRing(final SisaysRing card) {
super(card);
}
@Override
public SisaysRing copy() {
return new SisaysRing(this);
}
}

View file

@ -28,6 +28,7 @@
package mage.abilities; package mage.abilities;
import mage.abilities.costs.mana.ManaCost;
import mage.constants.AbilityType; import mage.constants.AbilityType;
import mage.constants.Zone; import mage.constants.Zone;
@ -37,17 +38,37 @@ import mage.constants.Zone;
*/ */
public abstract class SpecialAction extends ActivatedAbilityImpl { public abstract class SpecialAction extends ActivatedAbilityImpl {
private boolean manaAction;
protected ManaCost unpaidMana;
public SpecialAction() { public SpecialAction() {
this(Zone.ALL); this(Zone.ALL);
} }
public SpecialAction(Zone zone) { public SpecialAction(Zone zone) {
this(zone, false);
}
public SpecialAction(Zone zone, boolean manaAction) {
super(AbilityType.SPECIAL_ACTION, zone); super(AbilityType.SPECIAL_ACTION, zone);
this.usesStack = false; this.usesStack = false;
this.manaAction = manaAction;
} }
public SpecialAction(final SpecialAction action) { public SpecialAction(final SpecialAction action) {
super(action); super(action);
this.manaAction = action.manaAction;
this.unpaidMana = action.unpaidMana;
} }
public boolean isManaAction() {
return manaAction;
}
public void setUnpaidMana(ManaCost manaCost) {
this.unpaidMana = manaCost;
}
public ManaCost getUnpaidMana() {
return unpaidMana;
}
} }

View file

@ -28,6 +28,7 @@
package mage.abilities; package mage.abilities;
import java.util.Iterator;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.UUID; import java.util.UUID;
@ -43,10 +44,17 @@ public class SpecialActions extends AbilitiesImpl<SpecialAction> {
super(actions); super(actions);
} }
public LinkedHashMap<UUID, SpecialAction> getControlledBy(UUID controllerId) { /**
*
* @param controllerId
* @param manaAction true = if mana actions should get returned
* false = only non mana actions get returned
* @return
*/
public LinkedHashMap<UUID, SpecialAction> getControlledBy(UUID controllerId, boolean manaAction) {
LinkedHashMap<UUID, SpecialAction> controlledBy = new LinkedHashMap<>(); LinkedHashMap<UUID, SpecialAction> controlledBy = new LinkedHashMap<>();
for (SpecialAction action: this) { for (SpecialAction action: this) {
if (action.getControllerId().equals(controllerId)) { if (action.getControllerId().equals(controllerId) && action.isManaAction() == manaAction) {
controlledBy.put(action.id, action); controlledBy.put(action.id, action);
} }
} }
@ -58,4 +66,12 @@ public class SpecialActions extends AbilitiesImpl<SpecialAction> {
return new SpecialActions(this); return new SpecialActions(this);
} }
public void removeManaActions() {
for (Iterator<SpecialAction> iterator = this.iterator(); iterator.hasNext();) {
SpecialAction next = iterator.next();
if (next.isManaAction()) {
iterator.remove();
}
}
}
} }

View file

@ -31,6 +31,10 @@ public class AtTheEndOfCombatDelayedTriggeredAbility extends DelayedTriggeredAbi
@Override @Override
public String getRule() { public String getRule() {
return "At end of combat, " + modes.getText(); String ruleText = modes.getText();
if (ruleText.contains("at end of combat")) {
return ruleText;
}
return "At end of combat, " + ruleText;
} }
} }

View file

@ -28,6 +28,8 @@
package mage.abilities.costs.common; package mage.abilities.costs.common;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID; import java.util.UUID;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.costs.CostImpl; import mage.abilities.costs.CostImpl;
@ -46,10 +48,16 @@ import mage.util.CardUtil;
*/ */
public class ExileFromGraveCost extends CostImpl { public class ExileFromGraveCost extends CostImpl {
private final List<Card> exiledCards = new ArrayList<>();
public ExileFromGraveCost(TargetCardInYourGraveyard target) { public ExileFromGraveCost(TargetCardInYourGraveyard target) {
this.addTarget(target); this.addTarget(target);
if (target.getMaxNumberOfTargets() > 1) { if (target.getMaxNumberOfTargets() > 1) {
this.text = "Exile " + CardUtil.numberToText(target.getMaxNumberOfTargets()) + " " + target.getTargetName(); this.text = "Exile " +
(target.getNumberOfTargets() < target.getMaxNumberOfTargets() ? "up to ":"") +
CardUtil.numberToText(target.getMaxNumberOfTargets()) +
" " +
target.getTargetName();
} }
else { else {
this.text = "Exile " + target.getTargetName(); this.text = "Exile " + target.getTargetName();
@ -72,6 +80,7 @@ public class ExileFromGraveCost extends CostImpl {
public ExileFromGraveCost(final ExileFromGraveCost cost) { public ExileFromGraveCost(final ExileFromGraveCost cost) {
super(cost); super(cost);
this.exiledCards.addAll(cost.getExiledCards());
} }
@Override @Override
@ -84,6 +93,7 @@ public class ExileFromGraveCost extends CostImpl {
if (card == null || !game.getState().getZone(targetId).equals(Zone.GRAVEYARD)) { if (card == null || !game.getState().getZone(targetId).equals(Zone.GRAVEYARD)) {
return false; return false;
} }
exiledCards.add(card);
paid |= controller.moveCardToExileWithInfo(card, null, null, sourceId, game, Zone.GRAVEYARD); paid |= controller.moveCardToExileWithInfo(card, null, null, sourceId, game, Zone.GRAVEYARD);
} }
} }
@ -102,4 +112,7 @@ public class ExileFromGraveCost extends CostImpl {
return new ExileFromGraveCost(this); return new ExileFromGraveCost(this);
} }
public List<Card> getExiledCards() {
return exiledCards;
}
} }

View file

@ -0,0 +1,50 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.abilities.costs.mana;
import mage.abilities.Ability;
import mage.game.Game;
/**
* Interface for abilities that allow the player to pay mana costs of a spell in alternate ways.
* For the payment SpecialActions are used.
*
* Example of such an alternate payment ability: {@link mage.abilities.keyword.DelveAbility}
*
* @author LevelX2
*/
public interface AlternateManaPaymentAbility {
/**
* Adds the special action to the state, that allows the user to do the alternate mana payment
*
* @param source
* @param game
* @param unpaid unapaid mana costs of the spell
*/
void addSpecialAction(Ability source, Game game, ManaCost unpaid);
}

View file

@ -33,9 +33,11 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
import mage.MageObject;
import mage.Mana; import mage.Mana;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.costs.VariableCost; import mage.abilities.costs.VariableCost;
import mage.abilities.keyword.DelveAbility;
import mage.abilities.mana.ManaOptions; import mage.abilities.mana.ManaOptions;
import mage.constants.ColoredManaSymbol; import mage.constants.ColoredManaSymbol;
import mage.filter.Filter; import mage.filter.Filter;
@ -119,16 +121,36 @@ public class ManaCostsImpl<T extends ManaCost> extends ArrayList<T> implements M
Player player = game.getPlayer(controllerId); Player player = game.getPlayer(controllerId);
assignPayment(game, ability, player.getManaPool()); assignPayment(game, ability, player.getManaPool());
while (!isPaid()) { while (!isPaid()) {
addSpecialManaPayAbilities(ability, game);
if (player.playMana(this.getUnpaid(), game)) { if (player.playMana(this.getUnpaid(), game)) {
assignPayment(game, ability, player.getManaPool()); assignPayment(game, ability, player.getManaPool());
} } else {
else {
return false; return false;
} }
game.getState().getSpecialActions().removeManaActions();
} }
return true; return true;
} }
/**
* This activates the special button if there exists special ways to pay the mana (Delve, Convoke)
*
* @param ability
* @param game
*/
private void addSpecialManaPayAbilities(Ability source, Game game) {
// check for special mana payment possibilities
MageObject mageObject = source.getSourceObject(game);
if (mageObject != null) {
for (Ability ability :mageObject.getAbilities()) {
if (ability instanceof AlternateManaPaymentAbility) {
((AlternateManaPaymentAbility) ability).addSpecialAction(source, game, getUnpaid());
}
}
}
}
/** /**
* bookmarks the current state and restores it if player doesn't pay the mana cost * bookmarks the current state and restores it if player doesn't pay the mana cost
* *

View file

@ -40,7 +40,7 @@ public interface ContinuousRuleModifiyingEffect extends ContinuousEffect {
/** /**
* This check for the relevant events is called at first to prevent further actions if * This check for the relevant events is called at first to prevent further actions if
* the current event is ignored from this effect * the current event is ignored from this effect. Speeds up event handling.
* @param event * @param event
* @param game * @param game
* @return * @return

View file

@ -63,6 +63,16 @@ public abstract class ContinuousRuleModifiyingEffectImpl extends ContinuousEffec
this(duration, outcome, true, false); this(duration, outcome, true, false);
} }
/**
*
* @param duration
* @param outcome
* @param messageToUser - Every time the effect replaces an event, the user gets a message in a dialog window.
* Don't set it to true if the event heppens regularly or very often. The message can be
* changed by overriding the getInfoMessage method.
* @param messageToLog - Every time the effect replaces an event, a message is posted to the game log. The message
* can be changed by overriding the getInfoMessage method.
*/
public ContinuousRuleModifiyingEffectImpl(Duration duration, Outcome outcome, boolean messageToUser, boolean messageToLog) { public ContinuousRuleModifiyingEffectImpl(Duration duration, Outcome outcome, boolean messageToUser, boolean messageToLog) {
super(duration, outcome); super(duration, outcome);
this.effectType = EffectType.CONTINUOUS_RULE_MODIFICATION; this.effectType = EffectType.CONTINUOUS_RULE_MODIFICATION;
@ -78,6 +88,14 @@ public abstract class ContinuousRuleModifiyingEffectImpl extends ContinuousEffec
this.messageToGameLog = effect.messageToGameLog; this.messageToGameLog = effect.messageToGameLog;
} }
/**
* An early check for the event types this effect applies to. This check was added
* to speed up event handling. Once all existing ContinuousRuleModifiyingEffects have
* implemented this method, the method should be changed to abstract here or removed.
* @param event
* @param game
* @return
*/
@Override @Override
public boolean checksEventType(GameEvent event, Game game) { public boolean checksEventType(GameEvent event, Game game) {
return true; return true;

View file

@ -72,11 +72,17 @@ public class CreateDelayedTriggeredAbilityEffect extends OneShotEffect {
delayedAbility.setControllerId(source.getControllerId()); delayedAbility.setControllerId(source.getControllerId());
delayedAbility.setSourceObject(source.getSourceObject(game)); delayedAbility.setSourceObject(source.getSourceObject(game));
if (this.copyTargets) { if (this.copyTargets) {
if (source.getTargets().isEmpty()) {
for(Effect effect : delayedAbility.getEffects()) {
effect.setTargetPointer(targetPointer);
}
} else {
delayedAbility.getTargets().addAll(source.getTargets()); delayedAbility.getTargets().addAll(source.getTargets());
for(Effect effect : delayedAbility.getEffects()) { for(Effect effect : delayedAbility.getEffects()) {
effect.getTargetPointer().init(game, source); effect.getTargetPointer().init(game, source);
} }
} }
}
game.addDelayedTriggeredAbility(delayedAbility); game.addDelayedTriggeredAbility(delayedAbility);
return true; return true;
} }

View file

@ -28,28 +28,33 @@
package mage.abilities.keyword; package mage.abilities.keyword;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID; import java.util.UUID;
import mage.Mana;
import mage.ObjectColor; import mage.ObjectColor;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.SpellAbility; import mage.abilities.SpecialAction;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.AdjustingSourceCosts; import mage.abilities.costs.mana.AlternateManaPaymentAbility;
import mage.abilities.costs.mana.ManaCost; import mage.abilities.costs.mana.ManaCost;
import mage.abilities.costs.mana.ManaCosts; import mage.abilities.effects.OneShotEffect;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.choices.Choice; import mage.choices.Choice;
import mage.choices.ChoiceImpl; import mage.choices.ChoiceImpl;
import mage.constants.AbilityType;
import mage.constants.ManaType;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.constants.Zone; import mage.constants.Zone;
import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.Predicates; import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.ColorPredicate;
import mage.filter.predicate.permanent.TappedPredicate; import mage.filter.predicate.permanent.TappedPredicate;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.players.ManaPool;
import mage.players.Player; import mage.players.Player;
import mage.target.Target; import mage.target.Target;
import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetControlledCreaturePermanent;
import mage.util.CardUtil;
/* /*
* 502.46. Convoke * 502.46. Convoke
@ -84,13 +89,7 @@ import mage.util.CardUtil;
* *
* @author LevelX2 * @author LevelX2
*/ */
public class ConvokeAbility extends SimpleStaticAbility implements AdjustingSourceCosts { public class ConvokeAbility extends SimpleStaticAbility implements AlternateManaPaymentAbility {
private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent();
static {
filter.add(Predicates.not(new TappedPredicate()));
}
public ConvokeAbility() { public ConvokeAbility() {
super(Zone.STACK, null); super(Zone.STACK, null);
@ -107,96 +106,171 @@ public class ConvokeAbility extends SimpleStaticAbility implements AdjustingSour
} }
@Override @Override
public void adjustCosts(Ability ability, Game game) { public void addSpecialAction(Ability source, Game game, ManaCost unpaid) {
Player player = game.getPlayer(controllerId); Player controller = game.getPlayer(source.getControllerId());
if (player == null || !(ability instanceof SpellAbility)) { if (controller != null && controller.getGraveyard().size() > 0) {
return; if (unpaid.getMana().getColorless() > 0 && source.getAbilityType().equals(AbilityType.SPELL)) {
SpecialAction specialAction = new ConvokeSpecialAction(unpaid);
specialAction.setControllerId(source.getControllerId());
specialAction.setSourceId(source.getSourceId());
// create filter for possible creatures to tap
FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent();
filter.add(Predicates.not(new TappedPredicate()));
if (unpaid.getMana().getColorless() == 0) {
List<ColorPredicate> colorPredicates = new ArrayList<>();
if (unpaid.getMana().getBlack() > 0) {
colorPredicates.add(new ColorPredicate(ObjectColor.BLACK));
} }
Target target = new TargetControlledCreaturePermanent(1, Integer.MAX_VALUE, filter,true); if (unpaid.getMana().getBlue() > 0) {
target.setTargetName("creatures to convoke"); colorPredicates.add(new ColorPredicate(ObjectColor.BLUE));
if (!target.canChoose(sourceId, controllerId, game)) {
return;
} }
if (player.chooseUse(Outcome.Detriment, "Convoke creatures?", game)) { if (unpaid.getMana().getRed() > 0) {
player.chooseTarget(Outcome.Tap, target, ability, game); colorPredicates.add(new ColorPredicate(ObjectColor.RED));
if (target.getTargets().size() > 0) {
for (UUID creatureId: target.getTargets()) {
Permanent perm = game.getPermanent(creatureId);
if (perm == null || ability.getManaCostsToPay().convertedManaCost() == 0) {
continue;
} }
if (!perm.isTapped() && perm.tap(game)) { if (unpaid.getMana().getGreen() > 0) {
ManaCosts<ManaCost> manaCostsToReduce = new ManaCostsImpl<>(); colorPredicates.add(new ColorPredicate(ObjectColor.GREEN));
int costBefore = ability.getManaCostsToPay().convertedManaCost();
Choice chooseManaType = buildChoice(perm.getColor(), ability.getManaCostsToPay());
if (chooseManaType.getChoices().size() > 0) {
if (chooseManaType.getChoices().size() > 1) {
chooseManaType.getChoices().add("Colorless");
chooseManaType.setMessage("Choose mana color to reduce from " + perm.getName());
while (!chooseManaType.isChosen()) {
player.choose(Outcome.Benefit, chooseManaType, game);
} }
} else { if (unpaid.getMana().getWhite() > 0) {
chooseManaType.setChoice(chooseManaType.getChoices().iterator().next()); colorPredicates.add(new ColorPredicate(ObjectColor.WHITE));
} }
if (chooseManaType.getChoice().equals("Black")) { filter.add(Predicates.or(colorPredicates));
manaCostsToReduce.load("{B}");
} }
if (chooseManaType.getChoice().equals("Blue")) { Target target = new TargetControlledCreaturePermanent(1, 1, filter, true);
manaCostsToReduce.load("{U}"); target.setTargetName("creature to convoke");
} specialAction.addTarget(target);
if (chooseManaType.getChoice().equals("Green")) { if (specialAction.canActivate(source.getControllerId(), game)) {
manaCostsToReduce.load("{G}"); game.getState().getSpecialActions().add(specialAction);
}
if (chooseManaType.getChoice().equals("White")) {
manaCostsToReduce.load("{W}");
}
if (chooseManaType.getChoice().equals("Red")) {
manaCostsToReduce.load("{R}");
}
if (chooseManaType.getChoice().equals("Colorless")) {
manaCostsToReduce.load("{1}");
}
CardUtil.reduceCost((SpellAbility)ability, manaCostsToReduce);
} else {
manaCostsToReduce.load("{1}");
CardUtil.reduceCost((SpellAbility)ability, manaCostsToReduce);
}
if (costBefore == ability.getManaCostsToPay().convertedManaCost()) {
// creature could not reduce mana costs so tap must be reverted
perm.untap(game);
} else {
game.informPlayers("Convoke: " + player.getName() + " taps " + perm.getLogName() + " to reduce mana costs by " + manaCostsToReduce.getText());
} }
} }
} }
} }
}
}
private Choice buildChoice(ObjectColor creatureColor, ManaCosts manaCostsSpell) {
Choice choice = new ChoiceImpl();
String spellCosts = manaCostsSpell.getText();
if (creatureColor.isBlack() && spellCosts.contains("B")) {
choice.getChoices().add("Black");
}
if (creatureColor.isBlue() && spellCosts.contains("U")) {
choice.getChoices().add("Blue");
}
if (creatureColor.isGreen() && spellCosts.contains("G")) {
choice.getChoices().add("Green");
}
if (creatureColor.isRed() && spellCosts.contains("R")) {
choice.getChoices().add("Red");
}
if (creatureColor.isWhite() && spellCosts.contains("W")) {
choice.getChoices().add("White");
}
return choice;
}
@Override @Override
public String getRule() { public String getRule() {
return "Convoke <i>(Your creatures can help cast this spell. Each creature you tap while casting this spell pays for {1} or one mana of that creature's color.)</i>"; return "Convoke <i>(Your creatures can help cast this spell. Each creature you tap while casting this spell pays for {1} or one mana of that creature's color.)</i>";
} }
} }
class ConvokeSpecialAction extends SpecialAction {
public ConvokeSpecialAction(ManaCost unpaid) {
super(Zone.ALL, true);
setRuleVisible(false);
this.addEffect(new ConvokeEffect(unpaid));
}
public ConvokeSpecialAction(final ConvokeSpecialAction ability) {
super(ability);
}
@Override
public ConvokeSpecialAction copy() {
return new ConvokeSpecialAction(this);
}
}
class ConvokeEffect extends OneShotEffect {
private final ManaCost unpaid;
public ConvokeEffect(ManaCost unpaid) {
super(Outcome.Benefit);
this.unpaid = unpaid;
this.staticText = "Convoke (Your creatures can help cast this spell. Each creature you tap while casting this spell pays for {1} or one mana of that creature's color.)";
}
public ConvokeEffect(final ConvokeEffect effect) {
super(effect);
this.unpaid = effect.unpaid;
}
@Override
public ConvokeEffect copy() {
return new ConvokeEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
for (UUID creatureId: this.getTargetPointer().getTargets(game, source)) {
Permanent perm = game.getPermanent(creatureId);
if (perm == null) {
continue;
}
String manaName;
if (!perm.isTapped() && perm.tap(game)) {
ManaPool manaPool = controller.getManaPool();
Choice chooseManaType = buildChoice(perm.getColor(), unpaid.getMana());
if (chooseManaType.getChoices().size() > 0) {
if (chooseManaType.getChoices().size() > 1) {
chooseManaType.getChoices().add("Colorless");
chooseManaType.setMessage("Choose mana color to reduce from " + perm.getName());
while (!chooseManaType.isChosen()) {
controller.choose(Outcome.Benefit, chooseManaType, game);
if (!controller.isInGame()) {
return false;
}
}
} else {
chooseManaType.setChoice(chooseManaType.getChoices().iterator().next());
}
if (chooseManaType.getChoice().equals("Black")) {
manaPool.addMana(Mana.BlackMana, game, source);
manaPool.unlockManaType(ManaType.BLACK);
}
if (chooseManaType.getChoice().equals("Blue")) {
manaPool.addMana(Mana.BlueMana, game, source);
manaPool.unlockManaType(ManaType.BLUE);
}
if (chooseManaType.getChoice().equals("Green")) {
manaPool.addMana(Mana.GreenMana, game, source);
manaPool.unlockManaType(ManaType.GREEN);
}
if (chooseManaType.getChoice().equals("White")) {
manaPool.addMana(Mana.WhiteMana, game, source);
manaPool.unlockManaType(ManaType.WHITE);
}
if (chooseManaType.getChoice().equals("Red")) {
manaPool.addMana(Mana.RedMana, game, source);
manaPool.unlockManaType(ManaType.RED);
}
if (chooseManaType.getChoice().equals("Colorless")) {
manaPool.addMana(Mana.ColorlessMana, game, source);
manaPool.unlockManaType(ManaType.COLORLESS);
}
manaName = chooseManaType.getChoice().toLowerCase();
} else {
manaPool.addMana(Mana.ColorlessMana, game, source);
manaPool.unlockManaType(ManaType.COLORLESS);
manaName = "colorless";
}
game.informPlayers("Convoke: " + controller.getName() + " taps " + perm.getLogName() + " to pay one " + manaName + " mana");
}
}
return true;
}
return false;
}
private Choice buildChoice(ObjectColor creatureColor, Mana mana) {
Choice choice = new ChoiceImpl();
if (creatureColor.isBlack() && mana.getBlack() > 0) {
choice.getChoices().add("Black");
}
if (creatureColor.isBlue() && mana.getBlue() > 0) {
choice.getChoices().add("Blue");
}
if (creatureColor.isGreen() && mana.getGreen() > 0) {
choice.getChoices().add("Green");
}
if (creatureColor.isRed() && mana.getRed() > 0) {
choice.getChoices().add("Red");
}
if (creatureColor.isWhite() && mana.getWhite() > 0) {
choice.getChoices().add("White");
}
return choice;
}
}

View file

@ -29,18 +29,23 @@ package mage.abilities.keyword;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.UUID; import mage.Mana;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.SpellAbility; import mage.abilities.SpecialAction;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.AdjustingSourceCosts; import mage.abilities.costs.common.ExileFromGraveCost;
import mage.abilities.costs.mana.AlternateManaPaymentAbility;
import mage.abilities.costs.mana.ManaCost;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card; import mage.cards.Card;
import mage.constants.AbilityType;
import mage.constants.ManaType;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.constants.Zone; import mage.constants.Zone;
import mage.filter.FilterCard; import mage.filter.FilterCard;
import mage.game.Game; import mage.game.Game;
import mage.players.ManaPool;
import mage.players.Player; import mage.players.Player;
import mage.target.Target;
import mage.target.common.TargetCardInYourGraveyard; import mage.target.common.TargetCardInYourGraveyard;
import mage.util.CardUtil; import mage.util.CardUtil;
@ -71,22 +76,16 @@ import mage.util.CardUtil;
* increase the mana costs. * increase the mana costs.
*/ */
public class DelveAbility extends SimpleStaticAbility implements AdjustingSourceCosts { public class DelveAbility extends SimpleStaticAbility implements AlternateManaPaymentAbility {
private List<Card> delvedCards;
public DelveAbility() { public DelveAbility() {
super(Zone.STACK, null); super(Zone.STACK, null);
this.setRuleAtTheTop(true); this.setRuleAtTheTop(true);
this.delvedCards = null;
} }
public DelveAbility(final DelveAbility ability) { public DelveAbility(final DelveAbility ability) {
super(ability); super(ability);
if (ability.delvedCards != null) {
this.delvedCards = new ArrayList<>();
this.delvedCards.addAll(ability.delvedCards);
}
} }
@Override @Override
@ -95,46 +94,81 @@ import mage.util.CardUtil;
} }
@Override @Override
public void adjustCosts(Ability ability, Game game) { public String getRule() {
Player player = game.getPlayer(controllerId); return "Delve <i>(Each card you exile from your graveyard while casting this spell pays for {1})</i>";
if (player == null || !(ability instanceof SpellAbility)) {
return;
}
Target target = new TargetCardInYourGraveyard(1, Integer.MAX_VALUE, new FilterCard());
target.setTargetName("cards to delve from your graveyard");
target.setNotTarget(true);
if (!target.canChoose(sourceId, controllerId, game)) {
return;
}
if (!CardUtil.isCheckPlayableMode(ability) &&
player.chooseUse(Outcome.Detriment, "Delve cards from your graveyard?", game)) {
player.chooseTarget(Outcome.Detriment, target, ability, game);
if (target.getTargets().size() > 0) {
delvedCards = new ArrayList<>();
int adjCost = 0;
for (UUID cardId: target.getTargets()) {
Card card = game.getCard(cardId);
if (card == null) {
continue;
}
delvedCards.add(card);
player.moveCardToExileWithInfo(card, null, "", getSourceId(), game, Zone.GRAVEYARD);
++adjCost;
}
game.informPlayers(new StringBuilder("Delve: ").append(player.getName()).append(" exiled ")
.append(adjCost).append(" card").append(adjCost != 1?"s":"").append(" from his or her graveyard").toString());
CardUtil.adjustCost((SpellAbility)ability, adjCost);
}
}
} }
@Override @Override
public String getRule() { public void addSpecialAction(Ability source, Game game, ManaCost unpaid) {
return "Delve <i>(You may exile any number of cards from your graveyard as you cast this spell. It costs {1} less to cast for each card exiled this way.)</i>"; Player controller = game.getPlayer(source.getControllerId());
if (controller != null && controller.getGraveyard().size() > 0) {
if (unpaid.getMana().getColorless() > 0 && source.getAbilityType().equals(AbilityType.SPELL)) {
SpecialAction specialAction = new DelveSpecialAction();
specialAction.setControllerId(source.getControllerId());
specialAction.setSourceId(source.getSourceId());
specialAction.addCost(new ExileFromGraveCost(new TargetCardInYourGraveyard(
0, Math.min(controller.getGraveyard().size(), unpaid.getMana().getColorless()), new FilterCard())));
if (specialAction.canActivate(source.getControllerId(), game)) {
game.getState().getSpecialActions().add(specialAction);
}
}
}
}
} }
public List<Card> getDelvedCards() { class DelveSpecialAction extends SpecialAction {
return delvedCards;
public DelveSpecialAction() {
super(Zone.ALL, true);
this.addEffect(new DelveEffect());
} }
public DelveSpecialAction(final DelveSpecialAction ability) {
super(ability);
}
@Override
public DelveSpecialAction copy() {
return new DelveSpecialAction(this);
}
}
class DelveEffect extends OneShotEffect {
public DelveEffect() {
super(Outcome.Benefit);
this.staticText = "Delve (Each card you exile from your graveyard while casting this spell pays for {1}.)";
}
public DelveEffect(final DelveEffect effect) {
super(effect);
}
@Override
public DelveEffect copy() {
return new DelveEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
ExileFromGraveCost exileFromGraveCost = (ExileFromGraveCost) source.getCosts().get(0);
List<Card> exiledCards = exileFromGraveCost.getExiledCards();
if (exiledCards.size() > 0) {
ManaPool manaPool = controller.getManaPool();
manaPool.addMana(new Mana(0,0,0,0,0,exiledCards.size(),0), game, source);
manaPool.unlockManaType(ManaType.COLORLESS);
String keyString = CardUtil.getCardZoneString("delvedCards", source.getSourceId(), game);
List<Card> delvedCards = (List<Card>) game.getState().getValue(keyString);
if (delvedCards == null) {
game.getState().setValue(keyString, exiledCards);
} else {
delvedCards.addAll(exiledCards);
}
}
return true;
}
return false;
}
} }

View file

@ -85,7 +85,7 @@ public class ManaUtil {
chosenManaAbility = chosenManaAbilityForHybrid != null ? chosenManaAbilityForHybrid : chosenManaAbility; chosenManaAbility = chosenManaAbilityForHybrid != null ? chosenManaAbilityForHybrid : chosenManaAbility;
} }
if (countColored.size() == 0) { // seems there is no colorful mana we can pay for if (countColored.isEmpty()) { // seems there is no colorful mana we can pay for
// try to pay {1} // try to pay {1}
if (unpaidMana.getColorless() > 0) { if (unpaidMana.getColorless() > 0) {
// use any (lets choose first) // use any (lets choose first)