forked from External/mage
commit
dbf160bac3
92 changed files with 1417 additions and 753 deletions
|
|
@ -16,6 +16,7 @@ public class MagicCardsImageSource implements CardImageSource {
|
|||
|
||||
private static final Map<String, String> setNameTokenReplacement = new HashMap<String, String>() {
|
||||
{
|
||||
put("C15", "commander-2015");
|
||||
put("ORG", "oath-of-the-gatewatch");
|
||||
put("EXP", "zendikar-expeditions");
|
||||
put("BFZ", "battle-for-zendikar");
|
||||
|
|
|
|||
|
|
@ -99,6 +99,7 @@ public class WizardCardsImageSource implements CardImageSource {
|
|||
setsAliases.put("BTD", "Beatdown Box Set");
|
||||
setsAliases.put("C13", "Commander 2013 Edition");
|
||||
setsAliases.put("C14", "Commander 2014");
|
||||
setsAliases.put("C15", "Commander 2015");
|
||||
setsAliases.put("CHK", "Champions of Kamigawa");
|
||||
setsAliases.put("CHR", "Chronicles");
|
||||
setsAliases.put("CMD", "Magic: The Gathering-Commander");
|
||||
|
|
|
|||
|
|
@ -64,6 +64,6 @@ ddd=gvl
|
|||
unh=uh
|
||||
dde=pvc
|
||||
# Remove setname as soon as the images can be downloaded
|
||||
ignore.urls=TOK, OGW
|
||||
ignore.urls=TOK, OGW, C15
|
||||
# sets ordered by release time (newest goes first)
|
||||
token.lookup.order=OGW,EXP,DDP,BFZ,FVD,FVE,FVL,FVR,V12,V13,V14,V15,TPR,MPRP,DD3,DDO,ORI,MM2,PTC,DTK,FRF,KTK,M15,VMA,CNS,JOU,BNG,THS,DDL,M14,MMA,DGM,GTC,RTR,M13,AVR,DDI,DKA,ISD,M12,NPH,MBS,SOM,M11,ROE,DDE,WWK,ZEN,M10,GVL,ARB,DVD,CFX,JVC,ALA,EVE,SHM,EVG,MOR,LRW,10E,CLS,CHK,GRC
|
||||
token.lookup.order=C15,OGW,EXP,DDP,BFZ,FVD,FVE,FVL,FVR,V12,V13,V14,V15,TPR,MPRP,DD3,DDO,ORI,MM2,PTC,DTK,FRF,KTK,M15,VMA,CNS,JOU,BNG,THS,DDL,M14,MMA,DGM,GTC,RTR,M13,AVR,DDI,DKA,ISD,M12,NPH,MBS,SOM,M11,ROE,DDE,WWK,ZEN,M10,GVL,ARB,DVD,CFX,JVC,ALA,EVE,SHM,EVG,MOR,LRW,10E,CLS,CHK,GRC
|
||||
52
Mage.Sets/src/mage/sets/Commander2015.java
Normal file
52
Mage.Sets/src/mage/sets/Commander2015.java
Normal 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;
|
||||
|
||||
import java.util.GregorianCalendar;
|
||||
import mage.cards.ExpansionSet;
|
||||
import mage.constants.SetType;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author fireshoes
|
||||
*/
|
||||
|
||||
public class Commander2015 extends ExpansionSet {
|
||||
|
||||
private static final Commander2015 fINSTANCE = new Commander2015();
|
||||
|
||||
public static Commander2015 getInstance() {
|
||||
return fINSTANCE;
|
||||
}
|
||||
|
||||
private Commander2015() {
|
||||
super("Commander 2015 Edition", "C15", "mage.sets.commander2015", new GregorianCalendar(2015, 11, 13).getTime(), SetType.SUPPLEMENTAL);
|
||||
this.blockName = "Command Zone";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -52,7 +52,6 @@ public class SkirkCommando extends CardImpl {
|
|||
super(ownerId, 47, "Skirk Commando", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{1}{R}{R}");
|
||||
this.expansionSetCode = "ARC";
|
||||
this.subtype.add("Goblin");
|
||||
this.subtype.add("Shaman");
|
||||
|
||||
this.power = new MageInt(2);
|
||||
this.toughness = new MageInt(1);
|
||||
|
|
|
|||
|
|
@ -59,8 +59,7 @@ public class DustStalker extends CardImpl {
|
|||
public DustStalker(UUID ownerId) {
|
||||
super(ownerId, 202, "Dust Stalker", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{2}{B}{R}");
|
||||
this.expansionSetCode = "BFZ";
|
||||
this.supertype.add("Creautre");
|
||||
this.supertype.add("Eldrazi");
|
||||
this.subtype.add("Eldrazi");
|
||||
this.power = new MageInt(5);
|
||||
this.toughness = new MageInt(3);
|
||||
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ import mage.constants.Duration;
|
|||
import mage.constants.Outcome;
|
||||
import mage.constants.Rarity;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.filter.predicate.mageobject.AnotherTargetPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
|
|
@ -60,9 +61,23 @@ public class SerpentineSpike extends CardImpl {
|
|||
this.addAbility(ability);
|
||||
// Serpentine Spike deals 2 damage to target creature, 3 damage to another target creature, and 4 damage to a third target creature. If a creature dealt damage this way would die this turn, exile it instead.
|
||||
this.getSpellAbility().addEffect(new SerpentineSpikeEffect());
|
||||
this.getSpellAbility().addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature (2 damage)")));
|
||||
this.getSpellAbility().addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature (3 damage)")));
|
||||
this.getSpellAbility().addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature (4 damage)")));
|
||||
|
||||
TargetCreaturePermanent target = new TargetCreaturePermanent(new FilterCreaturePermanent("creature (2 damage)"));
|
||||
target.setTargetTag(1);
|
||||
this.getSpellAbility().addTarget(target);
|
||||
|
||||
FilterCreaturePermanent filter = new FilterCreaturePermanent("another target creature (3 damage)");
|
||||
filter.add(new AnotherTargetPredicate(2));
|
||||
target = new TargetCreaturePermanent(filter);
|
||||
target.setTargetTag(2);
|
||||
this.getSpellAbility().addTarget(target);
|
||||
|
||||
filter = new FilterCreaturePermanent("another target creature (4 damage)");
|
||||
filter.add(new AnotherTargetPredicate(3));
|
||||
target = new TargetCreaturePermanent(filter);
|
||||
target.setTargetTag(3);
|
||||
this.getSpellAbility().addTarget(target);
|
||||
|
||||
Effect effect = new DealtDamageToCreatureBySourceDies(this, Duration.EndOfTurn);
|
||||
effect.setText("If a creature dealt damage this way would die this turn, exile it instead");
|
||||
this.getSpellAbility().addEffect(effect);
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ public class GenjuOfTheRealm extends CardImpl {
|
|||
super(ownerId, 151, "Genju of the Realm", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{W}{U}{B}{R}{G}");
|
||||
this.expansionSetCode = "BOK";
|
||||
this.subtype.add("Aura");
|
||||
this.supertype.add("Legendary");
|
||||
|
||||
|
||||
// Enchant Land
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ public class MinamoSightbender extends CardImpl {
|
|||
this.subtype.add("Wizard");
|
||||
|
||||
this.power = new MageInt(1);
|
||||
this.toughness = new MageInt(1);
|
||||
this.toughness = new MageInt(2);
|
||||
|
||||
// {X}, {T}: Target creature with power X or less can't be blocked this turn.
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CantBeBlockedTargetEffect(), new ManaCostsImpl("{X}"));
|
||||
|
|
|
|||
|
|
@ -28,11 +28,11 @@
|
|||
package mage.sets.betrayersofkamigawa;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageObjectReference;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.PreventionEffectData;
|
||||
import mage.abilities.effects.PreventionEffectImpl;
|
||||
import mage.abilities.effects.RedirectionEffect;
|
||||
import mage.abilities.effects.common.AttachEffect;
|
||||
import mage.abilities.keyword.EnchantAbility;
|
||||
import mage.cards.CardImpl;
|
||||
|
|
@ -44,7 +44,6 @@ import mage.constants.Zone;
|
|||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetPermanent;
|
||||
import mage.target.common.TargetCreatureOrPlayer;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
|
|
@ -60,7 +59,6 @@ public class WardOfPiety extends CardImpl {
|
|||
this.expansionSetCode = "BOK";
|
||||
this.subtype.add("Aura");
|
||||
|
||||
|
||||
// Enchant creature
|
||||
TargetPermanent auraTarget = new TargetCreaturePermanent();
|
||||
this.getSpellAbility().addTarget(auraTarget);
|
||||
|
|
@ -84,10 +82,12 @@ public class WardOfPiety extends CardImpl {
|
|||
}
|
||||
}
|
||||
|
||||
class WardOfPietyPreventDamageTargetEffect extends PreventionEffectImpl {
|
||||
class WardOfPietyPreventDamageTargetEffect extends RedirectionEffect {
|
||||
|
||||
protected MageObjectReference redirectToObject;
|
||||
|
||||
public WardOfPietyPreventDamageTargetEffect() {
|
||||
super(Duration.EndOfTurn, 1, false, true);
|
||||
super(Duration.EndOfTurn, 1, true);
|
||||
staticText = "The next 1 damage that would be dealt to enchanted creature this turn is dealt to target creature or player instead";
|
||||
}
|
||||
|
||||
|
|
@ -106,35 +106,21 @@ class WardOfPietyPreventDamageTargetEffect extends PreventionEffectImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||
PreventionEffectData preventionData = preventDamageAction(event, source, game);
|
||||
// deal damage now
|
||||
if (preventionData.getPreventedDamage() > 0) {
|
||||
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
|
||||
if (permanent != null) {
|
||||
game.informPlayers("Dealing " + preventionData.getPreventedDamage() + " damage to " + permanent.getLogName() + " instead");
|
||||
// keep the original source id as it is redirecting
|
||||
permanent.damage(preventionData.getPreventedDamage(), event.getSourceId(), game, false, true);
|
||||
}
|
||||
Player player = game.getPlayer(getTargetPointer().getFirst(game, source));
|
||||
if (player != null) {
|
||||
game.informPlayers("Dealing " + preventionData.getPreventedDamage() + " damage to " + player.getLogName() + " instead");
|
||||
// keep the original source id as it is redirecting
|
||||
player.damage(preventionData.getPreventedDamage(), event.getSourceId(), game, false, true);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
public void init(Ability source, Game game) {
|
||||
super.init(source, game);
|
||||
redirectToObject = new MageObjectReference(source.getTargets().get(0).getFirstTarget(), game);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
if (super.applies(event, source, game)) {
|
||||
Permanent enchantment = game.getPermanent(source.getSourceId());
|
||||
if (enchantment != null && event.getTargetId().equals(enchantment.getAttachedTo())) {
|
||||
Permanent enchantment = game.getPermanent(source.getSourceId());
|
||||
if (enchantment != null && event.getTargetId().equals(enchantment.getAttachedTo())) {
|
||||
if (redirectToObject.equals(new MageObjectReference(source.getTargets().get(0).getFirstTarget(), game))) {
|
||||
redirectTarget = source.getTargets().get(0);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ public class CrushingPain extends CardImpl {
|
|||
public CrushingPain (UUID ownerId) {
|
||||
super(ownerId, 162, "Crushing Pain", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{1}{R}");
|
||||
this.expansionSetCode = "CHK";
|
||||
|
||||
this.subtype.add("Arcane");
|
||||
|
||||
// Crushing Pain deals 6 damage to target creature that was dealt damage this turn.
|
||||
this.getSpellAbility().addEffect(new DamageTargetEffect(6));
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ public class EtherealHaze extends CardImpl {
|
|||
public EtherealHaze (UUID ownerId) {
|
||||
super(ownerId, 9, "Ethereal Haze", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{W}");
|
||||
this.expansionSetCode = "CHK";
|
||||
|
||||
this.subtype.add("Arcane");
|
||||
|
||||
// Prevent all damage that would be dealt by creatures this turn.
|
||||
this.getSpellAbility().addEffect(new PreventAllDamageByAllEffect(new FilterCreaturePermanent("creatures"), Duration.EndOfTurn, false));
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ import mage.target.common.TargetCreaturePermanent;
|
|||
public class UnearthlyBlizzard extends CardImpl {
|
||||
|
||||
public UnearthlyBlizzard(UUID ownerId) {
|
||||
super(ownerId, 196, "Unearthly Blizzard", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{2}{R}");
|
||||
super(ownerId, 196, "Unearthly Blizzard", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{2}{R}");
|
||||
this.expansionSetCode = "CHK";
|
||||
this.subtype.add("Arcane");
|
||||
|
||||
|
|
|
|||
|
|
@ -31,8 +31,7 @@ import java.util.UUID;
|
|||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.mana.GenericManaCost;
|
||||
import mage.abilities.effects.PreventionEffectData;
|
||||
import mage.abilities.effects.PreventionEffectImpl;
|
||||
import mage.abilities.effects.RedirectionEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
|
|
@ -42,8 +41,7 @@ import mage.filter.common.FilterControlledCreaturePermanent;
|
|||
import mage.filter.predicate.mageobject.SupertypePredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetPlayer;
|
||||
import mage.target.common.TargetControlledCreaturePermanent;
|
||||
|
||||
/**
|
||||
|
|
@ -53,6 +51,7 @@ import mage.target.common.TargetControlledCreaturePermanent;
|
|||
public class VassalsDuty extends CardImpl {
|
||||
|
||||
private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("legendary creature you control");
|
||||
|
||||
static {
|
||||
filter.add(new SupertypePredicate("Legendary"));
|
||||
}
|
||||
|
|
@ -61,10 +60,9 @@ public class VassalsDuty extends CardImpl {
|
|||
super(ownerId, 48, "Vassal's Duty", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{3}{W}");
|
||||
this.expansionSetCode = "CHK";
|
||||
|
||||
|
||||
// {1}: The next 1 damage that would be dealt to target legendary creature you control this turn is dealt to you instead.
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new VassalsDutyPreventDamageTargetEffect(Duration.EndOfTurn, 1), new GenericManaCost(1));
|
||||
ability.addTarget(new TargetControlledCreaturePermanent(1,1,filter, false));
|
||||
ability.addTarget(new TargetControlledCreaturePermanent(1, 1, filter, false));
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
|
|
@ -78,10 +76,10 @@ public class VassalsDuty extends CardImpl {
|
|||
}
|
||||
}
|
||||
|
||||
class VassalsDutyPreventDamageTargetEffect extends PreventionEffectImpl {
|
||||
class VassalsDutyPreventDamageTargetEffect extends RedirectionEffect {
|
||||
|
||||
public VassalsDutyPreventDamageTargetEffect(Duration duration, int amount) {
|
||||
super(duration, amount, false);
|
||||
super(duration, amount, true);
|
||||
staticText = "The next " + amount + " damage that would be dealt to target legendary creature you control this turn is dealt to you instead";
|
||||
}
|
||||
|
||||
|
|
@ -94,29 +92,13 @@ class VassalsDutyPreventDamageTargetEffect extends PreventionEffectImpl {
|
|||
return new VassalsDutyPreventDamageTargetEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||
PreventionEffectData preventionResult = preventDamageAction(event, source, game);
|
||||
// deal damage now
|
||||
if (preventionResult.getPreventedDamage() > 0) {
|
||||
UUID redirectTo = source.getControllerId();
|
||||
Player player = game.getPlayer(redirectTo);
|
||||
if (player != null) {
|
||||
game.informPlayers("Dealing " + preventionResult.getPreventedDamage() + " to " + player.getLogName() + " instead");
|
||||
// keep the original source id as it is redirecting
|
||||
player.damage(preventionResult.getPreventedDamage(), event.getSourceId(), game, false, true);
|
||||
}
|
||||
}
|
||||
// damage amount is reduced or set to 0 so complete replacement of damage event is never neccessary
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
if (!this.used && super.applies(event, source, game)) {
|
||||
if (event.getTargetId().equals(getTargetPointer().getFirst(game, source))) {
|
||||
return game.getPermanent(event.getTargetId()) != null;
|
||||
}
|
||||
if (event.getTargetId().equals(getTargetPointer().getFirst(game, source))) {
|
||||
TargetPlayer target = new TargetPlayer();
|
||||
target.add(source.getControllerId(), game);
|
||||
redirectTarget = target;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ package mage.sets.coldsnap;
|
|||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.ActivatedAbilityImpl;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.common.DiscardTargetCost;
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
|
|
@ -59,7 +60,6 @@ public class LightningStorm extends CardImpl {
|
|||
super(ownerId, 89, "Lightning Storm", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{1}{R}{R}");
|
||||
this.expansionSetCode = "CSP";
|
||||
|
||||
|
||||
// Lightning Storm deals X damage to target creature or player, where X is 3 plus the number of charge counters on it.
|
||||
Effect effect = new DamageTargetEffect(new LightningStormCountCondition(CounterType.CHARGE));
|
||||
effect.setText("{this} deals X damage to target creature or player, where X is 3 plus the number of charge counters on it");
|
||||
|
|
@ -67,7 +67,7 @@ public class LightningStorm extends CardImpl {
|
|||
this.getSpellAbility().addTarget(new TargetCreatureOrPlayer());
|
||||
// Discard a land card: Put two charge counters on Lightning Storm. You may choose a new target for it. Any player may activate this ability but only if Lightning Storm is on the stack.
|
||||
SimpleActivatedAbility ability = new SimpleActivatedAbility(Zone.STACK,
|
||||
new LightningStormAddCounterEffect() ,
|
||||
new LightningStormAddCounterEffect(),
|
||||
new DiscardTargetCost(new TargetCardInHand(new FilterLandCard())));
|
||||
ability.setMayActivate(TargetController.ANY);
|
||||
ability.addEffect(new InfoEffect("Any player may activate this ability but only if {this} is on the stack"));
|
||||
|
|
@ -85,6 +85,7 @@ public class LightningStorm extends CardImpl {
|
|||
}
|
||||
|
||||
class LightningStormCountCondition implements DynamicValue {
|
||||
|
||||
private final CounterType counter;
|
||||
|
||||
public LightningStormCountCondition(CounterType counter) {
|
||||
|
|
@ -141,7 +142,7 @@ class LightningStormAddCounterEffect extends OneShotEffect {
|
|||
Spell spell = game.getStack().getSpell(source.getSourceId());
|
||||
if (spell != null) {
|
||||
spell.addCounters(CounterType.CHARGE.createInstance(2), game);
|
||||
return spell.chooseNewTargets(game, source.getControllerId(), false, false, null);
|
||||
return spell.chooseNewTargets(game, ((ActivatedAbilityImpl) source).getActivatorId(), false, false, null);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
52
Mage.Sets/src/mage/sets/commander2015/EternalWitness.java
Normal file
52
Mage.Sets/src/mage/sets/commander2015/EternalWitness.java
Normal 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.commander2015;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author fireshoes
|
||||
*/
|
||||
public class EternalWitness extends mage.sets.fifthdawn.EternalWitness {
|
||||
|
||||
public EternalWitness(UUID ownerId) {
|
||||
super(ownerId);
|
||||
this.cardNumber = 183;
|
||||
this.expansionSetCode = "C15";
|
||||
}
|
||||
|
||||
public EternalWitness(final EternalWitness card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EternalWitness copy() {
|
||||
return new EternalWitness(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
/*
|
||||
* 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.commander2015;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.common.SpellCastControllerTriggeredAbility;
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.common.continuous.BoostSourceEffect;
|
||||
import mage.abilities.effects.common.counter.AddCountersControllerEffect;
|
||||
import mage.abilities.keyword.DoubleStrikeAbility;
|
||||
import mage.abilities.keyword.VigilanceAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.Zone;
|
||||
import mage.counters.CounterType;
|
||||
import mage.filter.Filter;
|
||||
import mage.filter.FilterSpell;
|
||||
import mage.filter.predicate.mageobject.CardTypePredicate;
|
||||
import mage.filter.predicate.mageobject.ConvertedManaCostPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author fireshoes
|
||||
*/
|
||||
public class KalemneDiscipleOfIroas extends CardImpl {
|
||||
|
||||
private static final FilterSpell filterSpell = new FilterSpell("a creature spell with converted mana cost 5 or greater");
|
||||
|
||||
static {
|
||||
filterSpell.add(new CardTypePredicate(CardType.CREATURE));
|
||||
filterSpell.add(new ConvertedManaCostPredicate(Filter.ComparisonType.GreaterThan, 4));
|
||||
}
|
||||
|
||||
public KalemneDiscipleOfIroas(UUID ownerId) {
|
||||
super(ownerId, 999, "Kalemne, Disciple of Iroas", Rarity.MYTHIC, new CardType[]{CardType.CREATURE}, "{2}{R}{W}");
|
||||
this.expansionSetCode = "C15";
|
||||
this.supertype.add("Legendary");
|
||||
this.subtype.add("Giant");
|
||||
this.subtype.add("Soldier");
|
||||
this.power = new MageInt(3);
|
||||
this.toughness = new MageInt(3);
|
||||
|
||||
// Double strike
|
||||
this.addAbility(DoubleStrikeAbility.getInstance());
|
||||
|
||||
// Vigilance
|
||||
this.addAbility(VigilanceAbility.getInstance());
|
||||
|
||||
// Whenever you cast a creature spell with converted mana cost 5 or greater, you get an experience counter.
|
||||
Effect effect = new AddCountersControllerEffect(CounterType.EXPERIENCE.createInstance(1), false);
|
||||
effect.setText("you get an experience counter");
|
||||
Ability ability = new SpellCastControllerTriggeredAbility(effect, filterSpell, false);
|
||||
this.addAbility(ability);
|
||||
|
||||
// Kalemne, Disciple of Iroas gets +1/+1 for each experience counter you have.
|
||||
DynamicValue value = new SourceControllerExperienceCountersCount();
|
||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostSourceEffect(value, value, Duration.WhileOnBattlefield)));
|
||||
}
|
||||
|
||||
public KalemneDiscipleOfIroas(final KalemneDiscipleOfIroas card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public KalemneDiscipleOfIroas copy() {
|
||||
return new KalemneDiscipleOfIroas(this);
|
||||
}
|
||||
}
|
||||
|
||||
class SourceControllerExperienceCountersCount implements DynamicValue {
|
||||
|
||||
@Override
|
||||
public int calculate(Game game, Ability sourceAbility, Effect effect) {
|
||||
int amount = 0;
|
||||
Player player = game.getPlayer(sourceAbility.getControllerId());
|
||||
if (player != null) {
|
||||
amount = player.getCounters().getCount(CounterType.EXPERIENCE);
|
||||
}
|
||||
return amount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DynamicValue copy() {
|
||||
return new SourceControllerExperienceCountersCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "1";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return "experience counter you have";
|
||||
}
|
||||
}
|
||||
|
|
@ -63,6 +63,8 @@ public class EtherswornAdjudicator extends CardImpl {
|
|||
public EtherswornAdjudicator(UUID ownerId) {
|
||||
super(ownerId, 26, "Ethersworn Adjudicator", Rarity.MYTHIC, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{4}{U}");
|
||||
this.expansionSetCode = "CON";
|
||||
this.subtype.add("Vedalken");
|
||||
this.subtype.add("Knight");
|
||||
|
||||
this.power = new MageInt(4);
|
||||
this.toughness = new MageInt(4);
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ class PathToExileEffect extends OneShotEffect {
|
|||
if (player.searchLibrary(target, game)) {
|
||||
Card card = player.getLibrary().getCard(target.getFirstTarget(), game);
|
||||
if (card != null) {
|
||||
controller.moveCards(card, Zone.BATTLEFIELD, source, game, true, false, false, null);
|
||||
player.moveCards(card, Zone.BATTLEFIELD, source, game, true, false, false, null);
|
||||
}
|
||||
}
|
||||
player.shuffleLibrary(game);
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ public class ArchdemonOfGreed extends CardImpl {
|
|||
super(ownerId, 71, "Archdemon of Greed", Rarity.RARE, new CardType[]{CardType.CREATURE}, "");
|
||||
this.expansionSetCode = "DKA";
|
||||
this.subtype.add("Demon");
|
||||
this.color.setBlack(true);
|
||||
|
||||
this.nightCard = true;
|
||||
this.canTransform = true;
|
||||
|
|
|
|||
|
|
@ -32,20 +32,18 @@ import mage.Mana;
|
|||
import mage.ObjectColor;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.AsEntersBattlefieldAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.AttachEffect;
|
||||
import mage.abilities.effects.common.ChooseColorEffect;
|
||||
import mage.abilities.effects.common.ManaEffect;
|
||||
import mage.abilities.keyword.EnchantAbility;
|
||||
import mage.abilities.mana.TriggeredManaAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.choices.ChoiceColor;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.ColoredManaSymbol;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.common.FilterLandPermanent;
|
||||
import mage.filter.predicate.mageobject.SubtypePredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.GameEvent.EventType;
|
||||
|
|
@ -60,18 +58,13 @@ import mage.target.common.TargetLandPermanent;
|
|||
*/
|
||||
public class UtopiaSprawl extends CardImpl {
|
||||
|
||||
private static final FilterLandPermanent filter = new FilterLandPermanent("Forest");
|
||||
private static final FilterLandPermanent filter = new FilterLandPermanent("Forest", "Forest");
|
||||
|
||||
static {
|
||||
filter.add(new SubtypePredicate("Forest"));
|
||||
}
|
||||
|
||||
public UtopiaSprawl(UUID ownerId) {
|
||||
super(ownerId, 99, "Utopia Sprawl", Rarity.COMMON, new CardType[]{CardType.ENCHANTMENT}, "{G}");
|
||||
this.expansionSetCode = "DIS";
|
||||
this.subtype.add("Aura");
|
||||
|
||||
|
||||
// Enchant Forest
|
||||
TargetPermanent auraTarget = new TargetLandPermanent(filter);
|
||||
this.getSpellAbility().addTarget(auraTarget);
|
||||
|
|
@ -79,7 +72,7 @@ public class UtopiaSprawl extends CardImpl {
|
|||
Ability ability = new EnchantAbility(auraTarget.getTargetName());
|
||||
this.addAbility(ability);
|
||||
// As Utopia Sprawl enters the battlefield, choose a color.
|
||||
this.addAbility(new AsEntersBattlefieldAbility(new ChooseColorEffect()));
|
||||
this.addAbility(new AsEntersBattlefieldAbility(new ChooseColorEffect(Outcome.Detriment)));
|
||||
// Whenever enchanted Forest is tapped for mana, its controller adds one mana of the chosen color to his or her mana pool.
|
||||
this.addAbility(new UtopiaSprawlTriggeredAbility());
|
||||
}
|
||||
|
|
@ -94,42 +87,8 @@ public class UtopiaSprawl extends CardImpl {
|
|||
}
|
||||
}
|
||||
|
||||
class ChooseColorEffect extends OneShotEffect {
|
||||
|
||||
public ChooseColorEffect() {
|
||||
super(Outcome.BoostCreature);
|
||||
staticText = "choose a color";
|
||||
}
|
||||
|
||||
public ChooseColorEffect(final ChooseColorEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
Permanent permanent = game.getPermanent(source.getSourceId());
|
||||
if (player != null && permanent != null) {
|
||||
ChoiceColor colorChoice = new ChoiceColor();
|
||||
if (player.choose(Outcome.Neutral, colorChoice, game)) {
|
||||
game.informPlayers(permanent.getName() + ": " + player.getLogName() + " has chosen " + colorChoice.getChoice());
|
||||
game.getState().setValue(permanent.getId() + "_color", colorChoice.getColor());
|
||||
permanent.addInfo("chosen color", "<font color = 'blue'>Chosen color: " + colorChoice.getColor().getDescription() + "</font>", game);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChooseColorEffect copy() {
|
||||
return new ChooseColorEffect(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class UtopiaSprawlTriggeredAbility extends TriggeredManaAbility {
|
||||
|
||||
|
||||
public UtopiaSprawlTriggeredAbility() {
|
||||
super(Zone.BATTLEFIELD, new UtopiaSprawlEffect());
|
||||
}
|
||||
|
|
@ -146,10 +105,7 @@ class UtopiaSprawlTriggeredAbility extends TriggeredManaAbility {
|
|||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
Permanent enchantment = game.getPermanent(this.getSourceId());
|
||||
if (enchantment != null && event.getSourceId().equals(enchantment.getAttachedTo())) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return enchantment != null && event.getSourceId().equals(enchantment.getAttachedTo());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -159,11 +115,10 @@ class UtopiaSprawlTriggeredAbility extends TriggeredManaAbility {
|
|||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "Whenever enchanted Forest is tapped for mana, its controller adds one mana of the chosen color to his or her mana pool";
|
||||
return "Whenever enchanted Forest is tapped for mana, its controller adds one mana of the chosen color to his or her mana pool.";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class UtopiaSprawlEffect extends ManaEffect {
|
||||
|
||||
public UtopiaSprawlEffect() {
|
||||
|
|
@ -178,9 +133,9 @@ class UtopiaSprawlEffect extends ManaEffect {
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent enchantment = game.getPermanent(source.getSourceId());
|
||||
if(enchantment != null){
|
||||
if (enchantment != null) {
|
||||
Permanent land = game.getPermanent(enchantment.getAttachedTo());
|
||||
if(land != null){
|
||||
if (land != null) {
|
||||
Player player = game.getPlayer(land.getControllerId());
|
||||
if (player != null) {
|
||||
player.getManaPool().addMana(getMana(game, source), game, source);
|
||||
|
|
@ -205,4 +160,4 @@ class UtopiaSprawlEffect extends ManaEffect {
|
|||
public UtopiaSprawlEffect copy() {
|
||||
return new UtopiaSprawlEffect(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ public class SmeltWardGatekeepers extends CardImpl {
|
|||
super(ownerId, 39, "Smelt-Ward Gatekeepers", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{3}{R}");
|
||||
this.expansionSetCode = "DGM";
|
||||
this.subtype.add("Human");
|
||||
this.subtype.add("Soldier");
|
||||
this.subtype.add("Warrior");
|
||||
|
||||
this.power = new MageInt(2);
|
||||
this.toughness = new MageInt(4);
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ public class LivingLore extends CardImpl {
|
|||
this.addAbility(new EntersBattlefieldAbility(new LivingLoreExileEffect(), "exile an instant or sorcery card from your graveyard"));
|
||||
|
||||
// Living Lore's power and toughness are each equal to the exiled card's converted mana cost.
|
||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new LivingLoreSetPowerToughnessSourceEffect()));
|
||||
this.addAbility(new SimpleStaticAbility(Zone.ALL, new LivingLoreSetPowerToughnessSourceEffect()));
|
||||
|
||||
// Whenever Living Lore deals combat damage, you may sacrifice it. If you do, you may cast the exiled card without paying its mana cost.
|
||||
this.addAbility(new DealsCombatDamageTriggeredAbility(new LivingLoreSacrificeEffect(), true));
|
||||
|
|
@ -106,14 +106,14 @@ class LivingLoreExileEffect extends OneShotEffect {
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
MageObject sourceObject = source.getSourceObject(game);
|
||||
if (sourceObject != null && controller != null){
|
||||
Permanent sourcePermanent = game.getPermanentEntering(source.getSourceId());
|
||||
if (sourcePermanent != null && controller != null) {
|
||||
TargetCardInYourGraveyard target = new TargetCardInYourGraveyard(new FilterInstantOrSorceryCard("instant or sorcery card from your graveyard"));
|
||||
if (controller.chooseTarget(outcome, target, source, game)) {
|
||||
UUID exileId = CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter());
|
||||
UUID exileId = CardUtil.getExileZoneId(game, source.getSourceId(), game.getState().getZoneChangeCounter(source.getSourceId()) + 1);
|
||||
Card card = controller.getGraveyard().get(target.getFirstTarget(), game);
|
||||
if (card != null) {
|
||||
controller.moveCardToExileWithInfo(card, exileId, sourceObject.getIdName(), source.getSourceId(), game, Zone.GRAVEYARD, true);
|
||||
controller.moveCardsToExile(card, source, game, true, exileId, sourcePermanent.getIdName());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
|
@ -126,7 +126,7 @@ class LivingLoreExileEffect extends OneShotEffect {
|
|||
class LivingLoreSetPowerToughnessSourceEffect extends ContinuousEffectImpl {
|
||||
|
||||
public LivingLoreSetPowerToughnessSourceEffect() {
|
||||
super(Duration.WhileOnBattlefield, Layer.PTChangingEffects_7, SubLayer.SetPT_7b, Outcome.BoostCreature);
|
||||
super(Duration.Custom, Layer.PTChangingEffects_7, SubLayer.SetPT_7b, Outcome.BoostCreature);
|
||||
staticText = "{this}'s power and toughness are each equal to the exiled card's converted mana cost";
|
||||
}
|
||||
|
||||
|
|
@ -141,20 +141,23 @@ class LivingLoreSetPowerToughnessSourceEffect extends ContinuousEffectImpl {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
MageObject mageObject = source.getSourceObject(game);
|
||||
Permanent permanent = game.getPermanent(source.getSourceId());
|
||||
if (permanent != null && mageObject == null && new MageObjectReference(permanent, game).refersTo(mageObject, game)) {
|
||||
discard();
|
||||
return false;
|
||||
int zcc = game.getState().getZoneChangeCounter(source.getSourceId());
|
||||
if (permanent == null) {
|
||||
permanent = game.getPermanentEntering(source.getSourceId());
|
||||
zcc++;
|
||||
}
|
||||
UUID exileId = CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter());
|
||||
if (permanent == null) {
|
||||
return true;
|
||||
}
|
||||
UUID exileId = CardUtil.getExileZoneId(game, source.getSourceId(), zcc);
|
||||
if (exileId != null) {
|
||||
ExileZone exileZone = game.getExile().getExileZone(exileId);
|
||||
if (exileZone == null) {
|
||||
return false;
|
||||
}
|
||||
Card exiledCard = null;
|
||||
for (Card card :exileZone.getCards(game)) {
|
||||
for (Card card : exileZone.getCards(game)) {
|
||||
exiledCard = card;
|
||||
break;
|
||||
}
|
||||
|
|
@ -197,7 +200,7 @@ class LivingLoreSacrificeEffect extends OneShotEffect {
|
|||
ExileZone exileZone = game.getExile().getExileZone(exileId);
|
||||
Card exiledCard = null;
|
||||
if (exileZone != null) {
|
||||
for (Card card :exileZone.getCards(game)) {
|
||||
for (Card card : exileZone.getCards(game)) {
|
||||
exiledCard = card;
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@ import mage.constants.CardType;
|
|||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Rarity;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.filter.predicate.mageobject.AnotherTargetPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.target.TargetSource;
|
||||
|
|
@ -53,8 +55,15 @@ public class KorChant extends CardImpl {
|
|||
|
||||
// All damage that would be dealt this turn to target creature you control by a source of your choice is dealt to another target creature instead.
|
||||
this.getSpellAbility().addEffect(new KorChantEffect());
|
||||
this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent());
|
||||
this.getSpellAbility().addTarget(new KorChantSecondTarget());
|
||||
TargetControlledCreaturePermanent target = new TargetControlledCreaturePermanent();
|
||||
target.setTargetTag(1);
|
||||
this.getSpellAbility().addTarget(target);
|
||||
|
||||
FilterCreaturePermanent filter = new FilterCreaturePermanent("another target creature");
|
||||
filter.add(new AnotherTargetPredicate(2));
|
||||
TargetCreaturePermanent target2 = new TargetCreaturePermanent(filter);
|
||||
target2.setTargetTag(2);
|
||||
this.getSpellAbility().addTarget(target2);
|
||||
}
|
||||
|
||||
public KorChant(final KorChant card) {
|
||||
|
|
@ -67,33 +76,8 @@ public class KorChant extends CardImpl {
|
|||
}
|
||||
}
|
||||
|
||||
class KorChantSecondTarget extends TargetCreaturePermanent {
|
||||
|
||||
KorChantSecondTarget() {
|
||||
super();
|
||||
this.targetName = "another creature";
|
||||
}
|
||||
|
||||
KorChantSecondTarget(final KorChantSecondTarget target) {
|
||||
super(target);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canTarget(UUID controllerId, UUID id, Ability source, Game game) {
|
||||
if (source.getTargets().get(0).getTargets().contains(id)) {
|
||||
return false;
|
||||
}
|
||||
return super.canTarget(controllerId, id, source, game);
|
||||
}
|
||||
|
||||
@Override
|
||||
public KorChantSecondTarget copy() {
|
||||
return new KorChantSecondTarget(this);
|
||||
}
|
||||
}
|
||||
|
||||
class KorChantEffect extends RedirectionEffect {
|
||||
|
||||
|
||||
protected TargetSource target = new TargetSource();
|
||||
|
||||
KorChantEffect() {
|
||||
|
|
@ -121,7 +105,7 @@ class KorChantEffect extends RedirectionEffect {
|
|||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.DAMAGE_CREATURE;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
if (event.getTargetId().equals(this.getTargetPointer().getFirst(game, source))
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@ package mage.sets.fatereforged;
|
|||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.condition.LockedInCondition;
|
||||
import mage.abilities.condition.common.FerociousCondition;
|
||||
import mage.abilities.decorator.ConditionalContinuousRuleModifyingEffect;
|
||||
|
|
@ -41,7 +40,6 @@ import mage.constants.CardType;
|
|||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.target.common.TargetCreatureOrPlayer;
|
||||
|
|
@ -60,12 +58,12 @@ public class WildSlash extends CardImpl {
|
|||
ContinuousRuleModifyingEffect effect = new DamageCantBePreventedEffect();
|
||||
effect.setText("<i>Ferocious</i> — If you control a creature with power 4 or greater, damage can't be prevented this turn.<br>");
|
||||
this.getSpellAbility().addEffect(new ConditionalContinuousRuleModifyingEffect(effect,
|
||||
new LockedInCondition(FerociousCondition.getInstance())));
|
||||
|
||||
new LockedInCondition(FerociousCondition.getInstance())));
|
||||
|
||||
// Wild Slash deals 2 damage to target creature or player.
|
||||
this.getSpellAbility().addEffect(new DamageTargetEffect(2));
|
||||
this.getSpellAbility().addTarget(new TargetCreatureOrPlayer());
|
||||
|
||||
|
||||
}
|
||||
|
||||
public WildSlash(final WildSlash card) {
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ public class ShanodinDryads extends CardImpl {
|
|||
public ShanodinDryads(UUID ownerId) {
|
||||
super(ownerId, 187, "Shanodin Dryads", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{G}");
|
||||
this.expansionSetCode = "5ED";
|
||||
this.subtype.add("Nymph");
|
||||
this.subtype.add("Dryad");
|
||||
|
||||
this.power = new MageInt(1);
|
||||
|
|
|
|||
|
|
@ -46,16 +46,12 @@ public class UrbanEvolution extends CardImpl {
|
|||
public UrbanEvolution(UUID ownerId) {
|
||||
super(ownerId, 204, "Urban Evolution", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{3}{U}{G}");
|
||||
this.expansionSetCode = "GTC";
|
||||
this.subtype.add("Wizard");
|
||||
|
||||
|
||||
//Draw three cards.
|
||||
this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(3));
|
||||
|
||||
//You may play an additional land this turn.
|
||||
this.getSpellAbility().addEffect(new PlayAdditionalLandsControllerEffect(1, Duration.EndOfTurn));
|
||||
|
||||
|
||||
}
|
||||
|
||||
public UrbanEvolution(final UrbanEvolution card) {
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ public class UlashtTheHateSeed extends CardImpl {
|
|||
|
||||
// Ulasht, the Hate Seed enters the battlefield with a +1/+1 counter on it for each other red creature you control and a +1/+1 counter on it for each other green creature you control.
|
||||
this.addAbility(new EntersBattlefieldAbility(new UlashtTheHateSeedEffect(), "with a +1/+1 counter on it for each other red creature you control and a +1/+1 counter on it for each other green creature you control."));
|
||||
|
||||
|
||||
// {1}, Remove a +1/+1 counter from Ulasht: Choose one - Ulasht deals 1 damage to target creature;
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(1), new GenericManaCost(1));
|
||||
ability.addCost(new RemoveCountersSourceCost(CounterType.P1P1.createInstance()));
|
||||
|
|
@ -101,7 +101,7 @@ class UlashtTheHateSeedEffect extends OneShotEffect {
|
|||
|
||||
private static final FilterControlledCreaturePermanent filterGreen = new FilterControlledCreaturePermanent();
|
||||
private static final FilterControlledCreaturePermanent filterRed = new FilterControlledCreaturePermanent();
|
||||
|
||||
|
||||
static {
|
||||
filterGreen.add(new AnotherPredicate());
|
||||
filterGreen.add(new ColorPredicate(ObjectColor.GREEN));
|
||||
|
|
@ -121,7 +121,7 @@ class UlashtTheHateSeedEffect extends OneShotEffect {
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
Permanent permanent = game.getPermanent(source.getSourceId());
|
||||
Permanent permanent = game.getPermanentEntering(source.getSourceId());
|
||||
if (permanent != null && player != null) {
|
||||
int amount = game.getBattlefield().count(filterRed, source.getSourceId(), source.getControllerId(), game);
|
||||
amount += game.getBattlefield().count(filterGreen, source.getSourceId(), source.getControllerId(), game);
|
||||
|
|
@ -138,4 +138,4 @@ class UlashtTheHateSeedEffect extends OneShotEffect {
|
|||
return new UlashtTheHateSeedEffect(this);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ class UnbreathingHordeEffect1 extends OneShotEffect {
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
Permanent permanent = game.getPermanent(source.getSourceId());
|
||||
Permanent permanent = game.getPermanentEntering(source.getSourceId());
|
||||
if (permanent != null && player != null) {
|
||||
int amount = game.getBattlefield().countAll(filter1, source.getControllerId(), game) - 1;
|
||||
amount += player.getGraveyard().count(filter2, game);
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ import mage.constants.SubLayer;
|
|||
import mage.constants.Zone;
|
||||
import mage.filter.common.FilterControlledCreaturePermanent;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.filter.predicate.mageobject.AnotherTargetPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.target.common.TargetControlledCreaturePermanent;
|
||||
|
|
@ -66,8 +67,17 @@ public class DroolingGroodion extends CardImpl {
|
|||
// {2}{B}{G}, Sacrifice a creature: Target creature gets +2/+2 until end of turn. Another target creature gets -2/-2 until end of turn.
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DroolingGroodionEffect(), new ManaCostsImpl("{2}{B}{G}"));
|
||||
ability.addCost(new SacrificeTargetCost(new TargetControlledCreaturePermanent(1, 1, new FilterControlledCreaturePermanent(), true)));
|
||||
ability.addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature (first target)")));
|
||||
ability.addTarget(new TargetOtherCreaturePermanent(new FilterCreaturePermanent("creature (second target)")));
|
||||
|
||||
TargetCreaturePermanent target = new TargetCreaturePermanent(new FilterCreaturePermanent("creature (first target)"));
|
||||
target.setTargetTag(1);
|
||||
ability.addTarget(target);
|
||||
|
||||
FilterCreaturePermanent filter = new FilterCreaturePermanent("another target creature (second target");
|
||||
filter.add(new AnotherTargetPredicate(2));
|
||||
target = new TargetCreaturePermanent(filter);
|
||||
target.setTargetTag(2);
|
||||
ability.addTarget(target);
|
||||
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
|
|
@ -112,28 +122,3 @@ class DroolingGroodionEffect extends ContinuousEffectImpl {
|
|||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class TargetOtherCreaturePermanent extends TargetCreaturePermanent {
|
||||
|
||||
public TargetOtherCreaturePermanent(FilterCreaturePermanent filter) {
|
||||
super(filter);
|
||||
}
|
||||
|
||||
public TargetOtherCreaturePermanent(final TargetOtherCreaturePermanent target) {
|
||||
super(target);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canTarget(UUID controllerId, UUID id, Ability source, Game game) {
|
||||
if (source.getTargets().get(0).getTargets().contains(id)) {
|
||||
return false;
|
||||
}
|
||||
return super.canTarget(controllerId, id, source, game);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TargetOtherCreaturePermanent copy() {
|
||||
return new TargetOtherCreaturePermanent(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ public class PensiveMinotaur extends CardImpl {
|
|||
super(ownerId, 105, "Pensive Minotaur", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{2}{R}");
|
||||
this.expansionSetCode = "JOU";
|
||||
this.subtype.add("Minotaur");
|
||||
this.subtype.add("Warrior");
|
||||
|
||||
this.power = new MageInt(2);
|
||||
this.toughness = new MageInt(3);
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ import mage.target.common.TargetCreaturePermanent;
|
|||
public class FodderLaunch extends CardImpl {
|
||||
|
||||
public FodderLaunch(UUID ownerId) {
|
||||
super(ownerId, 114, "Fodder Launch", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{3}{B}");
|
||||
super(ownerId, 114, "Fodder Launch", Rarity.UNCOMMON, new CardType[]{CardType.TRIBAL, CardType.SORCERY}, "{3}{B}");
|
||||
this.expansionSetCode = "LRW";
|
||||
this.subtype.add("Goblin");
|
||||
|
||||
|
|
|
|||
|
|
@ -30,8 +30,7 @@ package mage.sets.magic2010;
|
|||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.PreventionEffectData;
|
||||
import mage.abilities.effects.PreventionEffectImpl;
|
||||
import mage.abilities.effects.RedirectionEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
|
|
@ -69,91 +68,65 @@ public class HarmsWay extends CardImpl {
|
|||
}
|
||||
}
|
||||
|
||||
class HarmsWayPreventDamageTargetEffect extends PreventionEffectImpl {
|
||||
|
||||
private final TargetSource target;
|
||||
|
||||
class HarmsWayPreventDamageTargetEffect extends RedirectionEffect {
|
||||
|
||||
private final TargetSource damageSource;
|
||||
|
||||
public HarmsWayPreventDamageTargetEffect() {
|
||||
super(Duration.EndOfTurn, 2, false, true);
|
||||
super(Duration.EndOfTurn, 2, true);
|
||||
staticText = "The next 2 damage that a source of your choice would deal to you and/or permanents you control this turn is dealt to target creature or player instead";
|
||||
this.target = new TargetSource();
|
||||
this.damageSource = new TargetSource();
|
||||
}
|
||||
|
||||
public HarmsWayPreventDamageTargetEffect(final HarmsWayPreventDamageTargetEffect effect) {
|
||||
super(effect);
|
||||
this.target = effect.target.copy();
|
||||
this.damageSource = effect.damageSource.copy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public HarmsWayPreventDamageTargetEffect copy() {
|
||||
return new HarmsWayPreventDamageTargetEffect(this);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void init(Ability source, Game game) {
|
||||
this.target.choose(Outcome.PreventDamage, source.getControllerId(), source.getSourceId(), game);
|
||||
this.damageSource.choose(Outcome.PreventDamage, source.getControllerId(), source.getSourceId(), game);
|
||||
super.init(source, game);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||
PreventionEffectData preventionData = preventDamageAction(event, source, game);
|
||||
// deal damage now
|
||||
if (preventionData.getPreventedDamage() > 0) {
|
||||
UUID redirectTo = source.getFirstTarget();
|
||||
Permanent permanent = game.getPermanent(redirectTo);
|
||||
if (permanent != null) {
|
||||
game.informPlayers("Dealing " + preventionData.getPreventedDamage() + " to " + permanent.getLogName() + " instead");
|
||||
// keep the original source id as it is redirecting
|
||||
permanent.damage(preventionData.getPreventedDamage(), event.getSourceId(), game, false, true);
|
||||
discard();
|
||||
}
|
||||
Player player = game.getPlayer(redirectTo);
|
||||
if (player != null) {
|
||||
game.informPlayers("Dealing " + preventionData.getPreventedDamage() + " to " + player.getLogName() + " instead");
|
||||
// keep the original source id as it is redirecting
|
||||
player.damage(preventionData.getPreventedDamage(), event.getSourceId(), game, false, true);
|
||||
discard();
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
// check source
|
||||
MageObject object = game.getObject(event.getSourceId());
|
||||
if (object == null) {
|
||||
game.informPlayers("Couldn't find source of damage");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!object.getId().equals(damageSource.getFirstTarget())
|
||||
&& (!(object instanceof Spell) || !((Spell) object).getSourceId().equals(damageSource.getFirstTarget()))) {
|
||||
return false;
|
||||
}
|
||||
this.redirectTarget = source.getTargets().get(0);
|
||||
|
||||
// check target
|
||||
// check permanent first
|
||||
Permanent permanent = game.getPermanent(event.getTargetId());
|
||||
if (permanent != null) {
|
||||
if (permanent.getControllerId().equals(source.getControllerId())) {
|
||||
// it's your permanent
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
if (super.applies(event, source, game)) {
|
||||
// check source
|
||||
MageObject object = game.getObject(event.getSourceId());
|
||||
if (object == null) {
|
||||
game.informPlayers("Couldn't find source of damage");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!object.getId().equals(target.getFirstTarget())
|
||||
&& (!(object instanceof Spell) || !((Spell) object).getSourceId().equals(target.getFirstTarget()))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// check target
|
||||
// check permanent first
|
||||
Permanent permanent = game.getPermanent(event.getTargetId());
|
||||
if (permanent != null) {
|
||||
if (permanent.getControllerId().equals(source.getControllerId())) {
|
||||
// it's your permanent
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// check player
|
||||
Player player = game.getPlayer(event.getTargetId());
|
||||
if (player != null) {
|
||||
if (player.getId().equals(source.getControllerId())) {
|
||||
// it is you
|
||||
return true;
|
||||
}
|
||||
// check player
|
||||
Player player = game.getPlayer(event.getTargetId());
|
||||
if (player != null) {
|
||||
if (player.getId().equals(source.getControllerId())) {
|
||||
// it is you
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -40,10 +40,6 @@ public class Lifelink extends mage.sets.magic2012.Lifelink {
|
|||
super(ownerId);
|
||||
this.cardNumber = 18;
|
||||
this.expansionSetCode = "M10";
|
||||
this.subtype.add("Aura");
|
||||
|
||||
this.color.setWhite(true);
|
||||
|
||||
}
|
||||
|
||||
public Lifelink (final Lifelink card) {
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ import mage.game.events.GameEvent.EventType;
|
|||
public class AjanisPridemate extends CardImpl {
|
||||
|
||||
public AjanisPridemate(UUID ownerId) {
|
||||
super(ownerId, 3, "Ajani's Pridemate", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "1}{W}");
|
||||
super(ownerId, 3, "Ajani's Pridemate", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{1}{W}");
|
||||
this.expansionSetCode = "M11";
|
||||
this.subtype.add("Cat");
|
||||
this.subtype.add("Soldier");
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
/*
|
||||
* Copyright 2011 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
|
|
@ -20,7 +20,7 @@
|
|||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
|
|
@ -49,7 +49,9 @@ public class RedSunsZenith extends CardImpl {
|
|||
super(ownerId, 74, "Red Sun's Zenith", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{X}{R}");
|
||||
this.expansionSetCode = "MBS";
|
||||
|
||||
|
||||
// Red Sun's Zenith deals X damage to target creature or player.
|
||||
// If a creature dealt damage this way would die this turn, exile it instead.
|
||||
// Shuffle Red Sun's Zenith into its owner's library.
|
||||
this.getSpellAbility().addTarget(new TargetCreatureOrPlayer());
|
||||
this.getSpellAbility().addEffect(new DamageTargetEffect(new ManacostVariableValue()));
|
||||
this.getSpellAbility().addEffect(new DealtDamageToCreatureBySourceDies(this, Duration.EndOfTurn));
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ class ToothAndNailPutCreatureOnBattlefieldEffect extends OneShotEffect {
|
|||
|
||||
TargetCardInHand target = new TargetCardInHand(0, 2, new FilterCreatureCard("creature cards"));
|
||||
if (controller.choose(Outcome.PutCreatureInPlay, target, source.getSourceId(), game)) {
|
||||
return controller.moveCards(new CardsImpl(getTargetPointer().getTargets(game, source)).getCards(game),
|
||||
return controller.moveCards(new CardsImpl(target.getTargets()).getCards(game),
|
||||
Zone.BATTLEFIELD, source, game, true, false, false, null);
|
||||
}
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ import mage.target.common.TargetCardInHand;
|
|||
public class BalshanGriffin extends CardImpl {
|
||||
|
||||
public BalshanGriffin(UUID ownerId) {
|
||||
super(ownerId, 67, "Balshan Griffin", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{3}{U}");
|
||||
super(ownerId, 67, "Balshan Griffin", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{3}{U}{U}");
|
||||
this.expansionSetCode = "ODY";
|
||||
this.subtype.add("Griffin");
|
||||
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ import mage.target.TargetSpell;
|
|||
public class FerventDenial extends CardImpl {
|
||||
|
||||
public FerventDenial(UUID ownerId) {
|
||||
super(ownerId, 86, "Fervent Denial", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{3}{U}");
|
||||
super(ownerId, 86, "Fervent Denial", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{3}{U}{U}");
|
||||
this.expansionSetCode = "ODY";
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -35,7 +35,6 @@ import mage.cards.CardImpl;
|
|||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.FilterCard;
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
@ -47,11 +46,10 @@ public class FutureSight extends CardImpl {
|
|||
super(ownerId, 84, "Future Sight", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}{U}{U}");
|
||||
this.expansionSetCode = "ONS";
|
||||
|
||||
|
||||
// Play with the top card of your library revealed.
|
||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new PlayWithTheTopCardRevealedEffect()));
|
||||
// You may play the top card of your library.
|
||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new PlayTheTopCardEffect(new FilterCard())));
|
||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new PlayTheTopCardEffect()));
|
||||
}
|
||||
|
||||
public FutureSight(final FutureSight card) {
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ import mage.players.Player;
|
|||
public class RiptideShapeshifter extends CardImpl {
|
||||
|
||||
public RiptideShapeshifter(UUID ownerId) {
|
||||
super(ownerId, 109, "Riptide Shapeshifter", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{3}{U}");
|
||||
super(ownerId, 109, "Riptide Shapeshifter", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{3}{U}{U}");
|
||||
this.expansionSetCode = "ONS";
|
||||
this.subtype.add("Shapeshifter");
|
||||
|
||||
|
|
|
|||
|
|
@ -29,11 +29,12 @@ package mage.sets.planechase;
|
|||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.MageObjectReference;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.PreventionEffectImpl;
|
||||
import mage.abilities.effects.RedirectionEffect;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.abilities.keyword.HasteAbility;
|
||||
import mage.abilities.keyword.VigilanceAbility;
|
||||
|
|
@ -42,9 +43,11 @@ 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.AnotherTargetPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.target.Target;
|
||||
import mage.target.common.TargetControlledCreaturePermanent;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
|
||||
|
|
@ -72,11 +75,18 @@ public class RaziaBorosArchangel extends CardImpl {
|
|||
// Haste
|
||||
this.addAbility(HasteAbility.getInstance());
|
||||
|
||||
// {tap}: The next 3 damage that would be dealt to target creature you control this turn is dealt to another target creature instead.
|
||||
// {T}: The next 3 damage that would be dealt to target creature you control this turn is dealt to another target creature instead.
|
||||
Effect effect = new RaziaBorosArchangelEffect(Duration.EndOfTurn, 3);
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new TapSourceCost());
|
||||
ability.addTarget(new TargetControlledCreaturePermanent());
|
||||
ability.addTarget(new TargetCreaturePermanent());
|
||||
Target target = new TargetControlledCreaturePermanent();
|
||||
target.setTargetTag(1);
|
||||
ability.addTarget(target);
|
||||
|
||||
FilterCreaturePermanent filter = new FilterCreaturePermanent("creature (damage is redirected to)");
|
||||
filter.add(new AnotherTargetPredicate(2));
|
||||
target = new TargetCreaturePermanent(filter);
|
||||
target.setTargetTag(2);
|
||||
ability.addTarget(target);
|
||||
this.addAbility(ability);
|
||||
|
||||
}
|
||||
|
|
@ -91,19 +101,17 @@ public class RaziaBorosArchangel extends CardImpl {
|
|||
}
|
||||
}
|
||||
|
||||
class RaziaBorosArchangelEffect extends PreventionEffectImpl {
|
||||
class RaziaBorosArchangelEffect extends RedirectionEffect {
|
||||
|
||||
private int amount;
|
||||
protected MageObjectReference redirectToObject;
|
||||
|
||||
public RaziaBorosArchangelEffect(Duration duration, int amount) {
|
||||
super(duration);
|
||||
this.amount = amount;
|
||||
super(duration, 3, true);
|
||||
staticText = "The next " + amount + " damage that would be dealt to target creature you control this turn is dealt to another target creature instead";
|
||||
}
|
||||
|
||||
public RaziaBorosArchangelEffect(final RaziaBorosArchangelEffect effect) {
|
||||
super(effect);
|
||||
this.amount = effect.amount;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -117,42 +125,16 @@ class RaziaBorosArchangelEffect extends PreventionEffectImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||
GameEvent preventEvent = new GameEvent(GameEvent.EventType.PREVENT_DAMAGE, source.getFirstTarget(), source.getSourceId(), source.getControllerId(), event.getAmount(), false);
|
||||
if (!game.replaceEvent(preventEvent)) {
|
||||
int prevented;
|
||||
if (event.getAmount() >= this.amount) {
|
||||
int damage = amount;
|
||||
event.setAmount(event.getAmount() - amount);
|
||||
this.used = true;
|
||||
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.PREVENTED_DAMAGE, source.getFirstTarget(), source.getSourceId(), source.getControllerId(), damage));
|
||||
prevented = damage;
|
||||
} else {
|
||||
int damage = event.getAmount();
|
||||
event.setAmount(0);
|
||||
amount -= damage;
|
||||
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.PREVENTED_DAMAGE, source.getFirstTarget(), source.getSourceId(), source.getControllerId(), damage));
|
||||
prevented = damage;
|
||||
}
|
||||
|
||||
// deal damage now
|
||||
if (prevented > 0) {
|
||||
UUID redirectTo = source.getTargets().get(1).getFirstTarget();
|
||||
Permanent permanent = game.getPermanent(redirectTo);
|
||||
if (permanent != null) {
|
||||
game.informPlayers("Dealing " + prevented + " to " + permanent.getName() + " instead");
|
||||
// keep the original source id as it is redirecting
|
||||
permanent.damage(prevented, event.getSourceId(), game, false, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
public void init(Ability source, Game game) {
|
||||
super.init(source, game);
|
||||
redirectToObject = new MageObjectReference(source.getTargets().get(1).getFirstTarget(), game);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
if (!this.used && super.applies(event, source, game)) {
|
||||
if (source.getTargets().getFirstTarget().equals(event.getTargetId())) {
|
||||
if (event.getTargetId().equals(getTargetPointer().getFirst(game, source))) {
|
||||
if (redirectToObject.equals(new MageObjectReference(source.getTargets().get(1).getFirstTarget(), game))) {
|
||||
redirectTarget = source.getTargets().get(1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,7 +40,6 @@ public class SilverMyr extends mage.sets.mirrodin.SilverMyr {
|
|||
super(ownerId);
|
||||
this.cardNumber = 126;
|
||||
this.expansionSetCode = "HOP";
|
||||
this.subtype.add("Myr");
|
||||
}
|
||||
|
||||
public SilverMyr (final SilverMyr card) {
|
||||
|
|
|
|||
|
|
@ -28,10 +28,6 @@
|
|||
package mage.sets.ravnica;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.Zone;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.EntersBattlefieldAbility;
|
||||
|
|
@ -42,6 +38,10 @@ import mage.abilities.effects.OneShotEffect;
|
|||
import mage.abilities.effects.common.RegenerateSourceEffect;
|
||||
import mage.abilities.keyword.DredgeAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.Zone;
|
||||
import mage.counters.CounterType;
|
||||
import mage.filter.common.FilterCreatureCard;
|
||||
import mage.filter.predicate.mageobject.CardTypePredicate;
|
||||
|
|
@ -104,7 +104,7 @@ class GolgariGraveTrollEffect extends OneShotEffect {
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
Permanent permanent = game.getPermanent(source.getSourceId());
|
||||
Permanent permanent = game.getPermanentEntering(source.getSourceId());
|
||||
if (permanent != null && player != null) {
|
||||
int amount = player.getGraveyard().count(filter, game);
|
||||
if (amount > 0) {
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ public class SphinxOfTheChimes extends CardImpl {
|
|||
public SphinxOfTheChimes(UUID ownerId) {
|
||||
super(ownerId, 52, "Sphinx of the Chimes", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{4}{U}{U}");
|
||||
this.expansionSetCode = "RTR";
|
||||
this.subtype.add("Bird");
|
||||
this.subtype.add("Sphinx");
|
||||
|
||||
this.power = new MageInt(5);
|
||||
this.toughness = new MageInt(6);
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ public class MatsuTribeBirdstalker extends CardImpl {
|
|||
this.expansionSetCode = "SOK";
|
||||
this.subtype.add("Snake");
|
||||
this.subtype.add("Warrior");
|
||||
this.subtype.add("Archer");
|
||||
|
||||
this.power = new MageInt(2);
|
||||
this.toughness = new MageInt(2);
|
||||
|
|
|
|||
|
|
@ -58,9 +58,12 @@ public class OxiddaDaredevil extends CardImpl {
|
|||
public OxiddaDaredevil (UUID ownerId) {
|
||||
super(ownerId, 100, "Oxidda Daredevil", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{1}{R}");
|
||||
this.expansionSetCode = "SOM";
|
||||
this.color.setRed(true);
|
||||
this.subtype.add("Goblin");
|
||||
this.subtype.add("Artificer");
|
||||
|
||||
this.power = new MageInt(2);
|
||||
this.toughness = new MageInt(1);
|
||||
|
||||
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD,
|
||||
new GainAbilitySourceEffect(HasteAbility.getInstance(), Duration.EndOfTurn),
|
||||
new SacrificeTargetCost(new TargetControlledPermanent(filter))));
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ public class GoblinWarchief extends CardImpl {
|
|||
super(ownerId, 97, "Goblin Warchief", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{1}{R}{R}");
|
||||
this.expansionSetCode = "SCG";
|
||||
this.subtype.add("Goblin");
|
||||
this.subtype.add("Warrior");
|
||||
|
||||
this.power = new MageInt(2);
|
||||
this.toughness = new MageInt(2);
|
||||
|
|
|
|||
|
|
@ -32,8 +32,10 @@ import mage.MageInt;
|
|||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.mana.GenericManaCost;
|
||||
import mage.abilities.effects.common.RedirectDamageFromSourceToTargetEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.Zone;
|
||||
import mage.target.common.TargetControlledCreaturePermanent;
|
||||
|
|
@ -55,7 +57,7 @@ public class NomadsEnKor extends CardImpl {
|
|||
this.toughness = new MageInt(1);
|
||||
|
||||
// {0}: The next 1 damage that would be dealt to Nomads en-Kor this turn is dealt to target creature you control instead.
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ShamanEnKorPreventionEffect(), new GenericManaCost(0));
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new RedirectDamageFromSourceToTargetEffect(Duration.EndOfTurn, 1, true), new GenericManaCost(0));
|
||||
ability.addTarget(new TargetControlledCreaturePermanent());
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
|
@ -68,4 +70,4 @@ public class NomadsEnKor extends CardImpl {
|
|||
public NomadsEnKor copy() {
|
||||
return new NomadsEnKor(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,14 +29,13 @@ package mage.sets.stronghold;
|
|||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.MageObject;
|
||||
import mage.MageObjectReference;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.mana.GenericManaCost;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.PreventionEffectData;
|
||||
import mage.abilities.effects.PreventionEffectImpl;
|
||||
import mage.abilities.effects.ReplacementEffectImpl;
|
||||
import mage.abilities.effects.RedirectionEffect;
|
||||
import mage.abilities.effects.common.RedirectDamageFromSourceToTargetEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
|
|
@ -44,11 +43,10 @@ import mage.constants.Outcome;
|
|||
import mage.constants.Rarity;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.DamageEvent;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.GameEvent.EventType;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetPermanent;
|
||||
import mage.target.TargetSource;
|
||||
import mage.target.common.TargetControlledCreaturePermanent;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
|
|
@ -70,12 +68,13 @@ public class ShamanEnKor extends CardImpl {
|
|||
this.toughness = new MageInt(2);
|
||||
|
||||
// {0}: The next 1 damage that would be dealt to Shaman en-Kor this turn is dealt to target creature you control instead.
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ShamanEnKorPreventionEffect(), new GenericManaCost(0));
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD,
|
||||
new RedirectDamageFromSourceToTargetEffect(Duration.EndOfTurn, 1, true), new GenericManaCost(0));
|
||||
ability.addTarget(new TargetControlledCreaturePermanent());
|
||||
this.addAbility(ability);
|
||||
|
||||
|
||||
// {1}{W}: The next time a source of your choice would deal damage to target creature this turn, that damage is dealt to Shaman en-Kor instead.
|
||||
ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ShamanEnKorReplacementEffect(), new ManaCostsImpl("{1}{W}"));
|
||||
ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ShamanEnKorRedirectFromTargetEffect(), new ManaCostsImpl("{1}{W}"));
|
||||
ability.addTarget(new TargetCreaturePermanent());
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
|
@ -90,129 +89,43 @@ public class ShamanEnKor extends CardImpl {
|
|||
}
|
||||
}
|
||||
|
||||
class ShamanEnKorPreventionEffect extends PreventionEffectImpl {
|
||||
|
||||
ShamanEnKorPreventionEffect() {
|
||||
super(Duration.EndOfTurn, 1, false);
|
||||
staticText = "The next 1 damage that would be dealt to {this} this turn is dealt to target creature you control instead.";
|
||||
}
|
||||
|
||||
ShamanEnKorPreventionEffect(final ShamanEnKorPreventionEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ShamanEnKorPreventionEffect copy() {
|
||||
return new ShamanEnKorPreventionEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||
PreventionEffectData preventionResult = preventDamageAction(event, source, game);
|
||||
if (preventionResult.getPreventedDamage() > 0) {
|
||||
Permanent redirectTo = game.getPermanent(getTargetPointer().getFirst(game, source));
|
||||
if (redirectTo != null) {
|
||||
game.informPlayers("Dealing " + preventionResult.getPreventedDamage() + " to " + redirectTo.getName() + " instead.");
|
||||
DamageEvent damageEvent = (DamageEvent) event;
|
||||
redirectTo.damage(preventionResult.getPreventedDamage(), event.getSourceId(), game, damageEvent.isCombatDamage(), damageEvent.isPreventable(), event.getAppliedEffects());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
if (!this.used && super.applies(event, source, game)) {
|
||||
if (event.getTargetId().equals(source.getSourceId())) {
|
||||
return game.getPermanent(getTargetPointer().getFirst(game, source)) != null;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
class ShamanEnKorRedirectFromTargetEffect extends RedirectionEffect {
|
||||
|
||||
class ShamanEnKorReplacementEffect extends ReplacementEffectImpl {
|
||||
|
||||
protected TargetSource targetSource;
|
||||
protected MageObjectReference sourceObject;
|
||||
|
||||
ShamanEnKorReplacementEffect() {
|
||||
super(Duration.EndOfTurn, Outcome.RedirectDamage);
|
||||
ShamanEnKorRedirectFromTargetEffect() {
|
||||
super(Duration.EndOfTurn, Integer.MAX_VALUE, true);
|
||||
staticText = "The next time a source of your choice would deal damage to target creature this turn, that damage is dealt to {this} instead";
|
||||
}
|
||||
|
||||
ShamanEnKorReplacementEffect(final ShamanEnKorReplacementEffect effect) {
|
||||
ShamanEnKorRedirectFromTargetEffect(final ShamanEnKorRedirectFromTargetEffect effect) {
|
||||
super(effect);
|
||||
targetSource = effect.targetSource;
|
||||
sourceObject = effect.sourceObject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Ability source, Game game) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
TargetSource target = new TargetSource();
|
||||
target.setNotTarget(true);
|
||||
if (player != null) {
|
||||
TargetSource target = new TargetSource();
|
||||
target.choose(Outcome.PreventDamage, player.getId(), source.getSourceId(), game);
|
||||
this.targetSource = target;
|
||||
this.sourceObject = new MageObjectReference(target.getFirstTarget(), game);
|
||||
} else {
|
||||
discard();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == EventType.DAMAGE_CREATURE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
if (!this.used) {
|
||||
if (targetSource != null) {
|
||||
if (event.getSourceId().equals(targetSource.getFirstTarget())) {
|
||||
// check source
|
||||
MageObject object = game.getObject(event.getSourceId());
|
||||
if (object == null) {
|
||||
game.informPlayers("Couldn't find source of damage");
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
if (event.getTargetId().equals(source.getFirstTarget())) {
|
||||
Permanent permanent = game.getPermanent(source.getFirstTarget());
|
||||
if (permanent != null) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||
DamageEvent damageEvent = (DamageEvent)event;
|
||||
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
|
||||
if (sourcePermanent != null) {
|
||||
// get name of old target
|
||||
Permanent targetPermanent = game.getPermanent(event.getTargetId());
|
||||
StringBuilder message = new StringBuilder();
|
||||
message.append(sourcePermanent.getName()).append(": gets ");
|
||||
message.append(damageEvent.getAmount()).append(" damage redirected from ");
|
||||
if (targetPermanent != null) {
|
||||
message.append(targetPermanent.getName());
|
||||
}
|
||||
else {
|
||||
Player targetPlayer = game.getPlayer(event.getTargetId());
|
||||
if (targetPlayer != null) {
|
||||
message.append(targetPlayer.getLogName());
|
||||
}
|
||||
else {
|
||||
message.append("unknown");
|
||||
}
|
||||
}
|
||||
game.informPlayers(message.toString());
|
||||
// redirect damage
|
||||
this.used = true;
|
||||
sourcePermanent.damage(damageEvent.getAmount(), damageEvent.getSourceId(), game, damageEvent.isCombatDamage(), damageEvent.isPreventable(), event.getAppliedEffects());
|
||||
return true;
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
if (sourceObject.equals(new MageObjectReference(event.getSourceId(), game))) {
|
||||
redirectTarget = new TargetPermanent();
|
||||
redirectTarget.add(source.getSourceId(), game);
|
||||
return event.getTargetId().equals(getTargetPointer().getFirst(game, source));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -223,7 +136,7 @@ class ShamanEnKorReplacementEffect extends ReplacementEffectImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public ShamanEnKorReplacementEffect copy() {
|
||||
return new ShamanEnKorReplacementEffect(this);
|
||||
public ShamanEnKorRedirectFromTargetEffect copy() {
|
||||
return new ShamanEnKorRedirectFromTargetEffect(this);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,9 +29,6 @@ package mage.sets.tempest;
|
|||
|
||||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
|
|
@ -42,7 +39,9 @@ import mage.cards.Card;
|
|||
import mage.cards.CardImpl;
|
||||
import mage.cards.Cards;
|
||||
import mage.cards.CardsImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
|
@ -91,15 +90,15 @@ class CursedScrollEffect extends OneShotEffect {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player you = game.getPlayer(source.getControllerId());
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
MageObject sourceObject = game.getObject(source.getSourceId());
|
||||
String cardName = (String) game.getState().getValue(source.getSourceId().toString() + NameACardEffect.INFO_KEY);
|
||||
if (sourceObject != null && you != null && cardName != null && !cardName.isEmpty()) {
|
||||
if (you.getHand().size() > 0) {
|
||||
if (sourceObject != null && controller != null && cardName != null && !cardName.isEmpty()) {
|
||||
if (controller.getHand().size() > 0) {
|
||||
Cards revealed = new CardsImpl();
|
||||
Card card = you.getHand().getRandom(game);
|
||||
Card card = controller.getHand().getRandom(game);
|
||||
revealed.add(card);
|
||||
you.revealCards(sourceObject.getName(), revealed, game);
|
||||
controller.revealCards(sourceObject.getIdName(), revealed, game);
|
||||
if (card.getName().equals(cardName)) {
|
||||
Permanent creature = game.getPermanent(targetPointer.getFirst(game, source));
|
||||
if (creature != null) {
|
||||
|
|
|
|||
|
|
@ -36,29 +36,39 @@ import mage.constants.CardType;
|
|||
import mage.constants.Outcome;
|
||||
import mage.constants.Rarity;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.filter.predicate.mageobject.AnotherTargetPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
import mage.target.targetpointer.SecondTargetPointer;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author fireshoes
|
||||
*/
|
||||
public class Deadshot extends CardImpl {
|
||||
|
||||
|
||||
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another target creature");
|
||||
|
||||
static {
|
||||
filter.add(new AnotherTargetPredicate(2));
|
||||
}
|
||||
|
||||
public Deadshot(UUID ownerId) {
|
||||
super(ownerId, 129, "Deadshot", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{3}{R}");
|
||||
this.expansionSetCode = "TPR";
|
||||
|
||||
// Tap target creature.
|
||||
this.getSpellAbility().addEffect(new TapTargetEffect());
|
||||
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
|
||||
|
||||
TargetCreaturePermanent target = new TargetCreaturePermanent();
|
||||
target.setTargetTag(1);
|
||||
this.getSpellAbility().addTarget(target);
|
||||
|
||||
// It deals damage equal to its power to another target creature.
|
||||
this.getSpellAbility().addEffect(new DeadshotDamageEffect());
|
||||
this.getSpellAbility().addTarget(new DeadshotTargetCreaturePermanent(filter));
|
||||
target = new TargetCreaturePermanent(filter);
|
||||
target.setTargetTag(2);
|
||||
this.getSpellAbility().addTarget(target);
|
||||
}
|
||||
|
||||
public Deadshot(final Deadshot card) {
|
||||
|
|
@ -80,6 +90,7 @@ class DeadshotDamageEffect extends OneShotEffect {
|
|||
|
||||
public DeadshotDamageEffect(final DeadshotDamageEffect effect) {
|
||||
super(effect);
|
||||
this.setTargetPointer(new SecondTargetPointer());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -89,10 +100,10 @@ class DeadshotDamageEffect extends OneShotEffect {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent ownCreature = game.getPermanent(source.getFirstTarget());
|
||||
Permanent ownCreature = game.getPermanentOrLKIBattlefield(source.getFirstTarget());
|
||||
if (ownCreature != null) {
|
||||
int damage = ownCreature.getPower().getValue();
|
||||
Permanent targetCreature = game.getPermanent(source.getTargets().get(1).getFirstTarget());
|
||||
Permanent targetCreature = game.getPermanent(getTargetPointer().getFirst(game, source));
|
||||
if (targetCreature != null) {
|
||||
targetCreature.damage(damage, ownCreature.getId(), game, false, true);
|
||||
return true;
|
||||
|
|
@ -101,27 +112,3 @@ class DeadshotDamageEffect extends OneShotEffect {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class DeadshotTargetCreaturePermanent extends TargetCreaturePermanent {
|
||||
|
||||
public DeadshotTargetCreaturePermanent(FilterCreaturePermanent filter) {
|
||||
super(filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canTarget(UUID id, Ability source, Game game) {
|
||||
if (source.getTargets().getFirstTarget().equals(id)) {
|
||||
return false;
|
||||
}
|
||||
return super.canTarget(id, source, game);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canTarget(UUID controllerId, UUID id, Ability source, Game game) {
|
||||
if (source.getTargets().getFirstTarget().equals(id)) {
|
||||
return false;
|
||||
}
|
||||
return super.canTarget(controllerId, id, source, game);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -32,18 +32,13 @@ import mage.MageInt;
|
|||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.mana.GenericManaCost;
|
||||
import mage.abilities.effects.PreventionEffectData;
|
||||
import mage.abilities.effects.PreventionEffectImpl;
|
||||
import mage.abilities.effects.common.RedirectDamageFromSourceToTargetEffect;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.DamageEvent;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.target.common.TargetControlledCreaturePermanent;
|
||||
|
||||
/**
|
||||
|
|
@ -62,9 +57,10 @@ public class SpiritEnKor extends CardImpl {
|
|||
|
||||
// Flying
|
||||
this.addAbility(FlyingAbility.getInstance());
|
||||
|
||||
|
||||
// {0}: The next 1 damage that would be dealt to Spirit en-Kor this turn is dealt to target creature you control instead.
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new SpiritEnKorPreventionEffect(), new GenericManaCost(0));
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD,
|
||||
new RedirectDamageFromSourceToTargetEffect(Duration.EndOfTurn, 1, true), new GenericManaCost(0));
|
||||
ability.addTarget(new TargetControlledCreaturePermanent());
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
|
@ -78,44 +74,3 @@ public class SpiritEnKor extends CardImpl {
|
|||
return new SpiritEnKor(this);
|
||||
}
|
||||
}
|
||||
|
||||
class SpiritEnKorPreventionEffect extends PreventionEffectImpl {
|
||||
|
||||
SpiritEnKorPreventionEffect() {
|
||||
super(Duration.EndOfTurn, 1, false);
|
||||
staticText = "The next 1 damage that would be dealt to {this} this turn is dealt to target creature you control instead.";
|
||||
}
|
||||
|
||||
SpiritEnKorPreventionEffect(final SpiritEnKorPreventionEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiritEnKorPreventionEffect copy() {
|
||||
return new SpiritEnKorPreventionEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||
PreventionEffectData preventionResult = preventDamageAction(event, source, game);
|
||||
if (preventionResult.getPreventedDamage() > 0) {
|
||||
Permanent redirectTo = game.getPermanent(getTargetPointer().getFirst(game, source));
|
||||
if (redirectTo != null) {
|
||||
game.informPlayers("Dealing " + preventionResult.getPreventedDamage() + " to " + redirectTo.getName() + " instead.");
|
||||
DamageEvent damageEvent = (DamageEvent) event;
|
||||
redirectTo.damage(preventionResult.getPreventedDamage(), event.getSourceId(), game, damageEvent.isCombatDamage(), damageEvent.isPreventable(), event.getAppliedEffects());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
if (!this.used && super.applies(event, source, game)) {
|
||||
if (event.getTargetId().equals(source.getSourceId())) {
|
||||
return game.getPermanent(getTargetPointer().getFirst(game, source)) != null;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -32,17 +32,12 @@ import mage.MageInt;
|
|||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.mana.GenericManaCost;
|
||||
import mage.abilities.effects.PreventionEffectData;
|
||||
import mage.abilities.effects.PreventionEffectImpl;
|
||||
import mage.abilities.effects.common.RedirectDamageFromSourceToTargetEffect;
|
||||
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.events.DamageEvent;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.target.common.TargetControlledCreaturePermanent;
|
||||
|
||||
/**
|
||||
|
|
@ -61,7 +56,8 @@ public class WarriorEnKor extends CardImpl {
|
|||
this.toughness = new MageInt(2);
|
||||
|
||||
// {0}: The next 1 damage that would be dealt to Warrior en-Kor this turn is dealt to target creature you control instead.
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new WarriorEnKorPreventionEffect(), new GenericManaCost(0));
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD,
|
||||
new RedirectDamageFromSourceToTargetEffect(Duration.EndOfTurn, 1, true), new GenericManaCost(0));
|
||||
ability.addTarget(new TargetControlledCreaturePermanent());
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
|
@ -75,44 +71,3 @@ public class WarriorEnKor extends CardImpl {
|
|||
return new WarriorEnKor(this);
|
||||
}
|
||||
}
|
||||
|
||||
class WarriorEnKorPreventionEffect extends PreventionEffectImpl {
|
||||
|
||||
WarriorEnKorPreventionEffect() {
|
||||
super(Duration.EndOfTurn, 1, false);
|
||||
staticText = "The next 1 damage that would be dealt to {this} this turn is dealt to target creature you control instead.";
|
||||
}
|
||||
|
||||
WarriorEnKorPreventionEffect(final WarriorEnKorPreventionEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WarriorEnKorPreventionEffect copy() {
|
||||
return new WarriorEnKorPreventionEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||
PreventionEffectData preventionResult = preventDamageAction(event, source, game);
|
||||
if (preventionResult.getPreventedDamage() > 0) {
|
||||
Permanent redirectTo = game.getPermanent(getTargetPointer().getFirst(game, source));
|
||||
if (redirectTo != null) {
|
||||
game.informPlayers("Dealing " + preventionResult.getPreventedDamage() + " to " + redirectTo.getName() + " instead.");
|
||||
DamageEvent damageEvent = (DamageEvent) event;
|
||||
redirectTo.damage(preventionResult.getPreventedDamage(), event.getSourceId(), game, damageEvent.isCombatDamage(), damageEvent.isPreventable(), event.getAppliedEffects());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
if (!this.used && super.applies(event, source, game)) {
|
||||
if (event.getTargetId().equals(source.getSourceId())) {
|
||||
return game.getPermanent(getTargetPointer().getFirst(game, source)) != null;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -50,11 +50,6 @@ public class Clone extends CardImpl {
|
|||
this.toughness = new MageInt(0);
|
||||
|
||||
// You may have Clone enter the battlefield as a copy of any creature on the battlefield.
|
||||
// ;
|
||||
// Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new EntersBattlefieldEffect(
|
||||
// new CopyPermanentEffect(),
|
||||
// "You may have {this} enter the battlefield as a copy of any creature on the battlefield",
|
||||
// true));
|
||||
this.addAbility(new EntersBattlefieldAbility(new CopyPermanentEffect(), true));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -48,7 +48,6 @@ public class HighwayRobber extends CardImpl {
|
|||
super(ownerId, 150, "Highway Robber", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{2}{B}{B}");
|
||||
this.expansionSetCode = "10E";
|
||||
this.subtype.add("Human");
|
||||
this.subtype.add("Rogue");
|
||||
this.subtype.add("Mercenary");
|
||||
|
||||
this.power = new MageInt(2);
|
||||
|
|
|
|||
|
|
@ -32,12 +32,13 @@ import mage.abilities.Ability;
|
|||
import mage.abilities.common.DiesAttachedTriggeredAbility;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.common.AttachEffect;
|
||||
import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect;
|
||||
import mage.abilities.effects.common.search.SearchLibraryPutInPlayTargetPlayerEffect;
|
||||
import mage.abilities.keyword.EnchantAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.SetTargetPointer;
|
||||
import mage.filter.common.FilterCreatureCard;
|
||||
import mage.target.TargetPermanent;
|
||||
import mage.target.common.TargetCardInLibrary;
|
||||
|
|
@ -54,7 +55,6 @@ public class PatternOfRebirth extends CardImpl {
|
|||
this.expansionSetCode = "UDS";
|
||||
this.subtype.add("Aura");
|
||||
|
||||
|
||||
// Enchant creature
|
||||
TargetPermanent auraTarget = new TargetCreaturePermanent();
|
||||
this.getSpellAbility().addTarget(auraTarget);
|
||||
|
|
@ -63,9 +63,9 @@ public class PatternOfRebirth extends CardImpl {
|
|||
this.addAbility(ability);
|
||||
|
||||
// When enchanted creature dies, that creature's controller may search his or her library for a creature card and put that card onto the battlefield. If that player does, he or she shuffles his or her library.
|
||||
Effect effect = new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(new FilterCreatureCard()), false, true, Outcome.PutCreatureInPlay);
|
||||
Effect effect = new SearchLibraryPutInPlayTargetPlayerEffect(new TargetCardInLibrary(new FilterCreatureCard()), false, true, Outcome.PutCreatureInPlay);
|
||||
effect.setText("that creature's controller may search his or her library for a creature card and put that card onto the battlefield. If that player does, he or she shuffles his or her library");
|
||||
this.addAbility(new DiesAttachedTriggeredAbility(effect, "enchanted creature", true, true));
|
||||
this.addAbility(new DiesAttachedTriggeredAbility(effect, "enchanted creature", true, true, SetTargetPointer.ATTACHED_TO_CONTROLLER));
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ public class GorillaWarrior extends CardImpl {
|
|||
super(ownerId, 256, "Gorilla Warrior", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{2}{G}");
|
||||
this.expansionSetCode = "USG";
|
||||
this.subtype.add("Ape");
|
||||
this.subtype.add("Warrior");
|
||||
|
||||
this.power = new MageInt(3);
|
||||
this.toughness = new MageInt(2);
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ import mage.game.permanent.Permanent;
|
|||
public class Sunder extends CardImpl {
|
||||
|
||||
public Sunder(UUID ownerId) {
|
||||
super(ownerId, 101, "Sunder", Rarity.RARE, new CardType[]{CardType.INSTANT}, "{3}{U}");
|
||||
super(ownerId, 101, "Sunder", Rarity.RARE, new CardType[]{CardType.INSTANT}, "{3}{U}{U}");
|
||||
this.expansionSetCode = "USG";
|
||||
|
||||
// Return all lands to their owners' hands.
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ public class ArrowVolleyTrap extends CardImpl {
|
|||
public ArrowVolleyTrap(UUID ownerId) {
|
||||
super(ownerId, 2, "Arrow Volley Trap", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{3}{W}{W}");
|
||||
this.expansionSetCode = "ZEN";
|
||||
this.subtype.add("Trap");
|
||||
|
||||
// If four or more creatures are attacking, you may pay {1}{W} rather than pay Arrow Volley Trap's mana cost.
|
||||
this.getSpellAbility().addAlternativeCost(new ArrowVolleyTrapAlternativeCost());
|
||||
|
|
|
|||
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package org.mage.test.cards.abilities.enters;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class SearchEntersBattlefieldTest extends CardTestPlayerBase {
|
||||
|
||||
@Test
|
||||
public void testLandAfterFetchUntapped() {
|
||||
addCard(Zone.HAND, playerA, "Verdant Catacombs");
|
||||
addCard(Zone.LIBRARY, playerA, "Forest");
|
||||
|
||||
playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Verdant Catacombs");
|
||||
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}, Pay");
|
||||
setChoice(playerA, "Forest");
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertGraveyardCount(playerA, "Verdant Catacombs", 1);
|
||||
assertPermanentCount(playerA, "Forest", 1);
|
||||
assertTapped("Forest", false);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -115,7 +115,7 @@ public class SpliceOnArcaneTest extends CardTestPlayerBase {
|
|||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4);
|
||||
// You may exile a green card with converted mana cost X from your hand rather than pay Nourishing Shoal's mana cost.
|
||||
// You gain X life.
|
||||
addCard(Zone.HAND, playerA, "Nourishing Shoal", 1);
|
||||
addCard(Zone.HAND, playerA, "Nourishing Shoal", 1); // {X}{G}{G}
|
||||
addCard(Zone.HAND, playerA, "Giant Growth", 1);
|
||||
// You may put a creature card from your hand onto the battlefield. That creature gains haste. Sacrifice that creature at the beginning of the next end step.
|
||||
// Splice onto Arcane {2}{R}{R} (As you cast an Arcane spell, you may reveal this card from your hand and pay its splice cost. If you do, add this card's effects to that spell.)
|
||||
|
|
|
|||
|
|
@ -147,4 +147,20 @@ public class SuspendTest extends CardTestPlayerBase {
|
|||
assertCounterOnExiledCardCount("Deep-Sea Kraken", CounterType.TIME, 8); // -1 from spell of player B
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAncestralVisionCantBeCastDirectly() {
|
||||
// Suspend 4-{U}
|
||||
// Target player draws three cards.
|
||||
addCard(Zone.HAND, playerA, "Ancestral Vision", 1);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Ancestral Vision", playerA);
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertHandCount(playerA, 1);
|
||||
assertHandCount(playerA, "Ancestral Vision", 1);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package org.mage.test.cards.planeswalker;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import mage.counters.CounterType;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class RedirectDamageToPlaneswalkerTest extends CardTestPlayerBase {
|
||||
|
||||
@Test
|
||||
public void testDirectDamage() {
|
||||
// +2: Look at the top card of target player's library. You may put that card on the bottom of that player's library.
|
||||
// 0: Draw three cards, then put two cards from your hand on top of your library in any order.
|
||||
// −1: Return target creature to its owner's hand.
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Jace, the Mind Sculptor"); // starts with 3 Loyality counters
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Mountain", 1);
|
||||
addCard(Zone.HAND, playerB, "Lightning Bolt");
|
||||
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "+2:", playerB);
|
||||
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Lightning Bolt", playerA);
|
||||
setChoice(playerB, "Yes");
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertPermanentCount(playerA, "Jace, the Mind Sculptor", 1);
|
||||
assertCounterCount("Jace, the Mind Sculptor", CounterType.LOYALTY, 2); // 3 + 2 - 3 = 2
|
||||
|
||||
assertGraveyardCount(playerB, "Lightning Bolt", 1);
|
||||
|
||||
assertLife(playerA, 20);
|
||||
assertLife(playerB, 20);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package org.mage.test.cards.replacement.prevent;
|
||||
package org.mage.test.cards.replacement.redirect;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
|
|
@ -6,15 +6,17 @@ import org.junit.Test;
|
|||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
/**
|
||||
* Harm's Way:
|
||||
* The next 2 damage that a source of your choice would deal to you and/or permanents you control this turn is dealt to target creature or player instead.
|
||||
* Harm's Way: The next 2 damage that a source of your choice would deal to you
|
||||
* and/or permanents you control this turn is dealt to target creature or player
|
||||
* instead.
|
||||
*
|
||||
* @author noxx
|
||||
*/
|
||||
public class HarmsWayRedirectDamageTest extends CardTestPlayerBase {
|
||||
|
||||
/**
|
||||
* Tests that 2 of 3 damage is redirected while 1 damage is still dealt to original target
|
||||
* Tests that 2 of 3 damage is redirected while 1 damage is still dealt to
|
||||
* original target
|
||||
*/
|
||||
@Test
|
||||
public void testRedirectTwoDamage() {
|
||||
|
|
@ -51,7 +53,7 @@ public class HarmsWayRedirectDamageTest extends CardTestPlayerBase {
|
|||
attack(2, playerB, "Craw Wurm");
|
||||
castSpell(2, PhaseStep.DECLARE_BLOCKERS, playerA, "Harm's Way", playerB);
|
||||
setChoice(playerA, "Craw Wurm");
|
||||
|
||||
|
||||
setStopAt(2, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
|
|
@ -79,8 +81,11 @@ public class HarmsWayRedirectDamageTest extends CardTestPlayerBase {
|
|||
addCard(Zone.BATTLEFIELD, playerB, "Magma Phoenix");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Harm's Way", playerB);
|
||||
setChoice(playerA, "Magma Phoenix");
|
||||
/** When Magma Phoenix dies, Magma Phoenix deals 3 damage to each creature and each player **/
|
||||
setChoice(playerA, "Magma Phoenix");
|
||||
/**
|
||||
* When Magma Phoenix dies, Magma Phoenix deals 3 damage to each
|
||||
* creature and each player *
|
||||
*/
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Lightning Bolt", "Magma Phoenix");
|
||||
|
||||
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||
|
|
@ -91,4 +96,38 @@ public class HarmsWayRedirectDamageTest extends CardTestPlayerBase {
|
|||
assertLife(playerB, 15); // 3 damage from dying Phoenix directly and 2 redirected damage from playerA
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that not preventable damage is redirected
|
||||
*/
|
||||
@Test
|
||||
public void testRedirectNotPreventableDamage() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain");
|
||||
// <i>Ferocious</i> If you control a creature with power 4 or greater, damage can't be prevented this turn.
|
||||
// Wild Slash deals 2 damage to target creature or player.
|
||||
addCard(Zone.HAND, playerA, "Wild Slash"); // {R}
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Serra Angel");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion");
|
||||
|
||||
// The next 2 damage that a source of your choice would deal to you and/or permanents
|
||||
// you control this turn is dealt to target creature or player instead.
|
||||
addCard(Zone.HAND, playerB, "Harm's Way"); // {W}
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Plains");
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Birds of Paradise");
|
||||
|
||||
// the 2 damage can't be prevented and have to be redirected to Silvercoat Lion of player A
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Wild Slash", "Birds of Paradise");
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Harm's Way", "Silvercoat Lion", "Wild Slash");
|
||||
setChoice(playerB, "Wild Slash");
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertGraveyardCount(playerA, "Wild Slash", 1);
|
||||
assertGraveyardCount(playerB, "Harm's Way", 1);
|
||||
assertPermanentCount(playerB, "Birds of Paradise", 1);
|
||||
assertGraveyardCount(playerA, "Silvercoat Lion", 1);
|
||||
assertLife(playerA, 20);
|
||||
assertLife(playerB, 20);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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 org.mage.test.cards.replacement.redirect;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class ShamenEnKorTest extends CardTestPlayerBase {
|
||||
|
||||
/**
|
||||
* Tests that 2 of 3 damage is redirected while 1 damage is still dealt to
|
||||
* original target
|
||||
*/
|
||||
@Test
|
||||
public void testFirstAbilityNonCombatDamage() {
|
||||
addCard(Zone.HAND, playerA, "Lightning Bolt");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain");
|
||||
|
||||
// {0}: The next 1 damage that would be dealt to Shaman en-Kor this turn is dealt to target creature you control instead.
|
||||
// {1}{W}: The next time a source of your choice would deal damage to target creature this turn, that damage is dealt to Shaman en-Kor instead.
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Shaman en-Kor"); // 1/2
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion"); // 2/2
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "Shaman en-Kor");
|
||||
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerB, "{0}: The next 1 damage", "Silvercoat Lion", "Lightning Bolt");
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerB, "{0}: The next 1 damage", "Silvercoat Lion", "Lightning Bolt");
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertGraveyardCount(playerA, "Lightning Bolt", 1);
|
||||
assertPermanentCount(playerB, "Shaman en-Kor", 1);
|
||||
assertGraveyardCount(playerB, "Silvercoat Lion", 1);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSecondAbilityNonCombatDamage() {
|
||||
addCard(Zone.HAND, playerA, "Lightning Bolt");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain");
|
||||
|
||||
// {0}: The next 1 damage that would be dealt to Shaman en-Kor this turn is dealt to target creature you control instead.
|
||||
// {1}{W}: The next time a source of your choice would deal damage to target creature this turn, that damage is dealt to Shaman en-Kor instead.
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Shaman en-Kor"); // 1/2
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Plains", 2);
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion"); // 2/2
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "Silvercoat Lion");
|
||||
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerB, "{1}{W}: The next time", "Silvercoat Lion", "Lightning Bolt");
|
||||
setChoice(playerB, "Lightning Bolt");
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertGraveyardCount(playerA, "Lightning Bolt", 1);
|
||||
assertPermanentCount(playerB, "Silvercoat Lion", 1);
|
||||
assertGraveyardCount(playerB, "Shaman en-Kor", 1);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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 org.mage.test.cards.replacement.redirect;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class WardOfPietyTest extends CardTestPlayerBase {
|
||||
|
||||
@Test
|
||||
public void testNonCombatDamageToPlayer() {
|
||||
addCard(Zone.HAND, playerB, "Lightning Bolt");
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Mountain");
|
||||
|
||||
// Enchant creature
|
||||
// {1}{W}: The next 1 damage that would be dealt to enchanted creature this turn is dealt to target creature or player instead.
|
||||
addCard(Zone.HAND, playerA, "Ward of Piety"); // {1}{W}
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion"); // 2/2
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 6);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Ward of Piety", "Silvercoat Lion");
|
||||
|
||||
activateAbility(1, PhaseStep.BEGIN_COMBAT, playerA, "{1}{W}: The next 1 damage", playerB);
|
||||
activateAbility(1, PhaseStep.BEGIN_COMBAT, playerA, "{1}{W}: The next 1 damage", playerB);
|
||||
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Lightning Bolt", "Silvercoat Lion");
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertGraveyardCount(playerB, "Lightning Bolt", 1);
|
||||
assertPermanentCount(playerA, "Ward of Piety", 1);
|
||||
assertPermanentCount(playerA, "Silvercoat Lion", 1);
|
||||
|
||||
assertLife(playerA, 20);
|
||||
assertLife(playerB, 18);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -192,4 +192,104 @@ public class OmniscienceTest extends CardTestPlayerBase {
|
|||
assertGraveyardCount(playerB, "Pillarfield Ox", 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* If another effect (e.g. Future Sight) allows you to cast nonland cards
|
||||
* from zones other than your hand, Xmage incorrectly lets you cast those
|
||||
* cards without paying their mana costs. Omniscience only lets you cast
|
||||
* spells from your hand without paying their mana costs.
|
||||
*/
|
||||
@Test
|
||||
public void testCastingWithFutureSight() {
|
||||
// You may cast nonland cards from your hand without paying their mana costs.
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Omniscience");
|
||||
// Play with the top card of your library revealed.
|
||||
// You may play the top card of your library.
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Future Sight", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 2);
|
||||
|
||||
addCard(Zone.LIBRARY, playerA, "Silvercoat Lion", 1);
|
||||
skipInitShuffling();
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Silvercoat Lion");
|
||||
setChoice(playerA, "Yes");
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertLife(playerA, 20);
|
||||
assertLife(playerB, 20);
|
||||
|
||||
assertPermanentCount(playerA, "Silvercoat Lion", 1);
|
||||
assertTapped("Plains", true); // plains have to be tapped because {2} have to be paid
|
||||
}
|
||||
|
||||
/**
|
||||
* If a spell has an additional cost (optional or mandatory, e.g. Entwine),
|
||||
* Omniscience incorrectly allows you cast the spell as if that cost had
|
||||
* been paid without paying that spell's mana cost. 117.9d If an alternative
|
||||
* cost is being paid to cast a spell, any additional costs, cost increases,
|
||||
* and cost reductions that affect that spell are applied to that
|
||||
* alternative cost. (See rule 601.2f.)
|
||||
*/
|
||||
@Test
|
||||
public void testCastingWithCyclonicRiftWithOverload() {
|
||||
// You may cast nonland cards from your hand without paying their mana costs.
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Omniscience");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 2);
|
||||
|
||||
// Choose one - Barbed Lightning deals 3 damage to target creature; or Barbed Lightning deals 3 damage to target player.
|
||||
// Entwine {2} (Choose both if you pay the entwine cost.)
|
||||
addCard(Zone.HAND, playerA, "Barbed Lightning", 1);
|
||||
|
||||
// Creature - 3/3 Swampwalk
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Bog Wraith", 1);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Barbed Lightning", "Bog Wraith");
|
||||
addTarget(playerA, playerB);
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertGraveyardCount(playerA, "Barbed Lightning", 1);
|
||||
assertGraveyardCount(playerB, "Bog Wraith", 1);
|
||||
|
||||
assertLife(playerA, 20);
|
||||
assertLife(playerB, 17);
|
||||
|
||||
assertTapped("Plains", true); // plains have to be tapped because {2} from Entwine have to be paid
|
||||
}
|
||||
|
||||
/**
|
||||
* If a spell has an unpayable cost (e.g. Ancestral Vision, which has no
|
||||
* mana cost), Omniscience should allow you to cast that spell without
|
||||
* paying its mana cost. In the case of Ancestral Vision, for example, Xmage
|
||||
* only gives you the option to suspend Ancestral Vision. 117.6a If an
|
||||
* unpayable cost is increased by an effect or an additional cost is
|
||||
* imposed, the cost is still unpayable. If an alternative cost is applied
|
||||
* to an unpayable cost, including an effect that allows a player to cast a
|
||||
* spell without paying its mana cost, the alternative cost may be paid.
|
||||
*/
|
||||
@Test
|
||||
public void testCastingUnpayableCost() {
|
||||
// You may cast nonland cards from your hand without paying their mana costs.
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Omniscience");
|
||||
|
||||
// Suspend 4-{U}
|
||||
// Target player draws three cards.
|
||||
addCard(Zone.HAND, playerA, "Ancestral Vision", 1);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Ancestral Vision", playerA);
|
||||
addTarget(playerA, playerB);
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertGraveyardCount(playerA, "Ancestral Vision", 1);
|
||||
|
||||
assertHandCount(playerA, 3);
|
||||
assertLife(playerA, 20);
|
||||
assertLife(playerB, 20);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package org.mage.test.cards.triggers;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class MelekIzzetParagonTest extends CardTestPlayerBase {
|
||||
|
||||
/**
|
||||
* Wenn Melek, Izzet Paragon liegt und man einen Red/Blue Sun's Zenith von
|
||||
* der Bib spielt, wird er nicht kopiert, auch wenn der Effekt auf dem Stack
|
||||
* sichtbar ist.
|
||||
*
|
||||
* Meine Theorie ist, dass die Kopie beim in die Bib mischen den Originalen
|
||||
* nimmt und er daher nicht mehr dem Stack ist um selbst verrechnet zu
|
||||
* werden
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testCopyZenith() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 5);
|
||||
// Play with the top card of your library revealed.
|
||||
// You may cast the top card of your library if it's an instant or sorcery card.
|
||||
// Whenever you cast an instant or sorcery spell from your library, copy it. You may choose new targets for the copy.
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Melek, Izzet Paragon");
|
||||
|
||||
// Red Sun's Zenith deals X damage to target creature or player.
|
||||
// If a creature dealt damage this way would die this turn, exile it instead.
|
||||
// Shuffle Red Sun's Zenith into its owner's library.
|
||||
addCard(Zone.LIBRARY, playerA, "Red Sun's Zenith"); // {X}{R}
|
||||
skipInitShuffling();
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Red Sun's Zenith", playerB);
|
||||
setChoice(playerA, "X=4");
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertGraveyardCount(playerA, "Red Sun's Zenith", 0);
|
||||
|
||||
assertLife(playerA, 20);
|
||||
assertLife(playerB, 12);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -471,7 +471,10 @@ public abstract class AbilityImpl implements Ability {
|
|||
}
|
||||
// controller specific alternate spell costs
|
||||
if (!noMana && !alternativeCostisUsed) {
|
||||
if (this.getAbilityType().equals(AbilityType.SPELL)) {
|
||||
if (this.getAbilityType().equals(AbilityType.SPELL)
|
||||
// 117.9a Only one alternative cost can be applied to any one spell as it’s being cast.
|
||||
// So an alternate spell ability can't be paid with Omniscience
|
||||
&& !((SpellAbility) this).getSpellAbilityType().equals(SpellAbilityType.BASE_ALTERNATE)) {
|
||||
for (AlternativeSourceCosts alternativeSourceCosts : controller.getAlternativeSourceCosts()) {
|
||||
if (alternativeSourceCosts.isAvailable(this, game)) {
|
||||
if (alternativeSourceCosts.askToActivateAlternativeCosts(this, game)) {
|
||||
|
|
|
|||
|
|
@ -99,10 +99,6 @@ public class SpellAbility extends ActivatedAbilityImpl {
|
|||
&& !controllerId.equals(playerId)) {
|
||||
return false;
|
||||
}
|
||||
// Check if spell has no costs (not {0} mana costs), than it's not castable. E.g. for spells like Living End, that only can be cast by Suspend Ability.
|
||||
if (this.getManaCosts().isEmpty() && this.getCosts().isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
// Check if rule modifying events prevent to cast the spell in check playable mode
|
||||
if (this.isCheckPlayableMode()) {
|
||||
if (game.getContinuousEffects().preventedByRuleModification(
|
||||
|
|
|
|||
|
|
@ -2,11 +2,13 @@ package mage.abilities.common;
|
|||
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.constants.SetTargetPointer;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.ZoneChangeEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
|
||||
/**
|
||||
* "When enchanted/equipped creature dies" triggered ability
|
||||
|
|
@ -17,6 +19,7 @@ public class DiesAttachedTriggeredAbility extends TriggeredAbilityImpl {
|
|||
|
||||
private String attachedDescription;
|
||||
private boolean diesRuleText;
|
||||
protected SetTargetPointer setTargetPointer;
|
||||
|
||||
public DiesAttachedTriggeredAbility(Effect effect, String attachedDescription) {
|
||||
this(effect, attachedDescription, false);
|
||||
|
|
@ -27,15 +30,21 @@ public class DiesAttachedTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
public DiesAttachedTriggeredAbility(Effect effect, String attachedDescription, boolean optional, boolean diesRuleText) {
|
||||
this(effect, attachedDescription, optional, diesRuleText, SetTargetPointer.NONE);
|
||||
}
|
||||
|
||||
public DiesAttachedTriggeredAbility(Effect effect, String attachedDescription, boolean optional, boolean diesRuleText, SetTargetPointer setTargetPointer) {
|
||||
super(Zone.ALL, effect, optional); // because the trigger only triggers if the object was attached, it doesn't matter where the Attachment was moved to (e.g. by replacement effect) after the trigger triggered, so Zone.all
|
||||
this.attachedDescription = attachedDescription;
|
||||
this.diesRuleText = diesRuleText;
|
||||
this.setTargetPointer = setTargetPointer;
|
||||
}
|
||||
|
||||
public DiesAttachedTriggeredAbility(final DiesAttachedTriggeredAbility ability) {
|
||||
super(ability);
|
||||
this.attachedDescription = ability.attachedDescription;
|
||||
this.diesRuleText = ability.diesRuleText;
|
||||
this.setTargetPointer = ability.setTargetPointer;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -69,6 +78,16 @@ public class DiesAttachedTriggeredAbility extends TriggeredAbilityImpl {
|
|||
if (triggered) {
|
||||
for (Effect effect : getEffects()) {
|
||||
effect.setValue("attachedTo", zEvent.getTarget());
|
||||
if (setTargetPointer.equals(SetTargetPointer.ATTACHED_TO_CONTROLLER)) {
|
||||
Permanent attachment = game.getPermanentOrLKIBattlefield(getSourceId());
|
||||
if (attachment != null && attachment.getAttachedTo() != null) {
|
||||
Permanent attachedTo = (Permanent) game.getLastKnownInformation(attachment.getAttachedTo(), Zone.BATTLEFIELD, attachment.getAttachedToZoneChangeCounter());
|
||||
if (attachedTo != null) {
|
||||
effect.setTargetPointer(new FixedTarget(attachedTo.getControllerId()));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ package mage.abilities.costs;
|
|||
|
||||
import java.util.Iterator;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.abilities.StaticAbility;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.abilities.costs.mana.ManaCost;
|
||||
|
|
@ -39,6 +40,7 @@ import mage.constants.Zone;
|
|||
import mage.filter.FilterCard;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
@ -145,28 +147,39 @@ public class AlternativeCostSourceAbility extends StaticAbility implements Alter
|
|||
}
|
||||
Player player = game.getPlayer(ability.getControllerId());
|
||||
if (player != null) {
|
||||
Costs<AlternativeCost2> alternativeCosts;
|
||||
Costs<AlternativeCost2> alternativeCostsToCheck;
|
||||
if (dynamicCost != null) {
|
||||
alternativeCosts = new CostsImpl<>();
|
||||
alternativeCosts.add(convertToAlternativeCost(dynamicCost.getCost(ability, game)));
|
||||
alternativeCostsToCheck = new CostsImpl<>();
|
||||
alternativeCostsToCheck.add(convertToAlternativeCost(dynamicCost.getCost(ability, game)));
|
||||
} else {
|
||||
alternativeCosts = this.alternateCosts;
|
||||
alternativeCostsToCheck = this.alternateCosts;
|
||||
}
|
||||
|
||||
String costChoiceText;
|
||||
if (dynamicCost != null) {
|
||||
costChoiceText = dynamicCost.getText(ability, game);
|
||||
} else {
|
||||
costChoiceText = alternativeCosts.isEmpty() ? "Cast without paying its mana cost?" : "Pay alternative costs? (" + alternativeCosts.getText() + ")";
|
||||
costChoiceText = alternativeCostsToCheck.isEmpty() ? "Cast without paying its mana cost?" : "Pay alternative costs? (" + alternativeCostsToCheck.getText() + ")";
|
||||
}
|
||||
|
||||
if (alternativeCosts.canPay(ability, ability.getSourceId(), ability.getControllerId(), game)
|
||||
if (alternativeCostsToCheck.canPay(ability, ability.getSourceId(), ability.getControllerId(), game)
|
||||
&& player.chooseUse(Outcome.Benefit, costChoiceText, this, game)) {
|
||||
ability.getManaCostsToPay().clear();
|
||||
if (ability instanceof SpellAbility) {
|
||||
for (Iterator<ManaCost> iterator = ability.getManaCostsToPay().iterator(); iterator.hasNext();) {
|
||||
ManaCost manaCost = iterator.next();
|
||||
if (manaCost instanceof VariableCost) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
CardUtil.reduceCost((SpellAbility) ability, ability.getManaCosts());
|
||||
|
||||
} else {
|
||||
ability.getManaCostsToPay().clear();
|
||||
}
|
||||
if (!onlyMana) {
|
||||
ability.getCosts().clear();
|
||||
}
|
||||
for (Cost cost : alternativeCosts) {
|
||||
for (Cost cost : alternativeCostsToCheck) {
|
||||
AlternativeCost2 alternateCost = (AlternativeCost2) cost;
|
||||
alternateCost.activate();
|
||||
for (Iterator it = ((Costs) alternateCost).iterator(); it.hasNext();) {
|
||||
|
|
@ -190,14 +203,14 @@ public class AlternativeCostSourceAbility extends StaticAbility implements Alter
|
|||
|
||||
@Override
|
||||
public boolean isActivated(Ability source, Game game) {
|
||||
Costs<AlternativeCost2> alternativeCosts;
|
||||
Costs<AlternativeCost2> alternativeCostsToCheck;
|
||||
if (dynamicCost != null) {
|
||||
alternativeCosts = new CostsImpl<>();
|
||||
alternativeCosts.add(convertToAlternativeCost(dynamicCost.getCost(source, game)));
|
||||
alternativeCostsToCheck = new CostsImpl<>();
|
||||
alternativeCostsToCheck.add(convertToAlternativeCost(dynamicCost.getCost(source, game)));
|
||||
} else {
|
||||
alternativeCosts = this.alternateCosts;
|
||||
alternativeCostsToCheck = this.alternateCosts;
|
||||
}
|
||||
for (AlternativeCost2 cost : alternativeCosts) {
|
||||
for (AlternativeCost2 cost : alternativeCostsToCheck) {
|
||||
if (cost.isActivated(game)) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
|
|
@ -20,12 +20,11 @@
|
|||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
package mage.abilities.effects;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
|
|
@ -46,36 +45,67 @@ import mage.target.Target;
|
|||
public abstract class RedirectionEffect extends ReplacementEffectImpl {
|
||||
|
||||
protected Target redirectTarget;
|
||||
protected int amountToRedirect;
|
||||
protected boolean oneUsage;
|
||||
|
||||
public RedirectionEffect(Duration duration) {
|
||||
this(duration, Integer.MAX_VALUE, false);
|
||||
}
|
||||
|
||||
public RedirectionEffect(Duration duration, int amountToRedirect, boolean oneUsage) {
|
||||
super(duration, Outcome.RedirectDamage);
|
||||
this.effectType = EffectType.REDIRECTION;
|
||||
this.amountToRedirect = amountToRedirect;
|
||||
this.oneUsage = oneUsage;
|
||||
}
|
||||
|
||||
public RedirectionEffect(final RedirectionEffect effect) {
|
||||
super(effect);
|
||||
this.redirectTarget = effect.redirectTarget;
|
||||
this.amountToRedirect = effect.amountToRedirect;
|
||||
this.oneUsage = effect.oneUsage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||
DamageEvent damageEvent = (DamageEvent)event;
|
||||
Permanent permanent = game.getPermanent(redirectTarget.getFirstTarget());
|
||||
if (permanent != null) {
|
||||
permanent.damage(damageEvent.getAmount(), event.getSourceId(), game, damageEvent.isCombatDamage(), damageEvent.isPreventable(), event.getAppliedEffects());
|
||||
return true;
|
||||
}
|
||||
Player player = game.getPlayer(redirectTarget.getFirstTarget());
|
||||
if (player != null) {
|
||||
player.damage(damageEvent.getAmount(), event.getSourceId(), game, damageEvent.isCombatDamage(), damageEvent.isPreventable(), event.getAppliedEffects());
|
||||
return true;
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
switch (event.getType()) {
|
||||
case DAMAGE_CREATURE:
|
||||
case DAMAGE_PLAYER:
|
||||
case DAMAGE_PLANESWALKER:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||
String sourceLogName = source != null ? game.getObject(source.getSourceId()).getLogName() + ": " : "";
|
||||
DamageEvent damageEvent = (DamageEvent) event;
|
||||
int restDamage = 0;
|
||||
int damageToRedirect = event.getAmount();
|
||||
if (damageEvent.getAmount() > amountToRedirect) {
|
||||
restDamage = damageEvent.getAmount() - amountToRedirect;
|
||||
damageToRedirect = amountToRedirect;
|
||||
}
|
||||
if (damageToRedirect > 0 && oneUsage) {
|
||||
this.discard();
|
||||
}
|
||||
Permanent permanent = game.getPermanent(redirectTarget.getFirstTarget());
|
||||
if (permanent != null) {
|
||||
permanent.damage(damageToRedirect, event.getSourceId(), game, damageEvent.isCombatDamage(), damageEvent.isPreventable(), event.getAppliedEffects());
|
||||
game.informPlayers(sourceLogName + "Redirected " + damageToRedirect + " damage to " + permanent.getLogName());
|
||||
} else {
|
||||
Player player = game.getPlayer(redirectTarget.getFirstTarget());
|
||||
if (player != null) {
|
||||
player.damage(damageToRedirect, event.getSourceId(), game, damageEvent.isCombatDamage(), damageEvent.isPreventable(), event.getAppliedEffects());
|
||||
game.informPlayers(sourceLogName + "Redirected " + damageToRedirect + " damage to " + player.getLogName());
|
||||
}
|
||||
}
|
||||
if (restDamage > 0) {
|
||||
damageEvent.setAmount(restDamage);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ public class NameACardEffect extends OneShotEffect {
|
|||
Player controller = game.getPlayer(source.getControllerId());
|
||||
MageObject sourceObject = game.getPermanentEntering(source.getSourceId());
|
||||
if (sourceObject == null) {
|
||||
game.getObject(source.getSourceId());
|
||||
sourceObject = game.getObject(source.getSourceId());
|
||||
}
|
||||
if (controller != null && sourceObject != null) {
|
||||
Choice cardChoice = new ChoiceImpl();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package mage.abilities.effects.common;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.RedirectionEffect;
|
||||
import mage.constants.Duration;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class RedirectDamageFromSourceToTargetEffect extends RedirectionEffect {
|
||||
|
||||
public RedirectDamageFromSourceToTargetEffect(Duration duration, int amountToRedirect, boolean oneUsage) {
|
||||
super(duration, amountToRedirect, oneUsage);
|
||||
staticText = "The next " + amountToRedirect + " damage that would be dealt to {this} this turn is dealt to target creature you control instead.";
|
||||
}
|
||||
|
||||
public RedirectDamageFromSourceToTargetEffect(final RedirectDamageFromSourceToTargetEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RedirectDamageFromSourceToTargetEffect copy() {
|
||||
return new RedirectDamageFromSourceToTargetEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
if (event.getTargetId().equals(source.getSourceId())) {
|
||||
this.redirectTarget = source.getTargets().get(0);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,37 +1,35 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.abilities.effects.common;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.MageSingleton;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
|
|
@ -59,15 +57,15 @@ public class ShuffleSpellEffect extends OneShotEffect implements MageSingleton {
|
|||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller != null) {
|
||||
Spell spell = game.getStack().getSpell(source.getSourceId());
|
||||
// We have to use the spell id because in case of copied spells, the sourceId can be multiple times on the stack
|
||||
Spell spell = game.getStack().getSpell(source.getId());
|
||||
if (spell != null) {
|
||||
Card spellCard = spell.getCard();
|
||||
if (spellCard != null) {
|
||||
Player owner = game.getPlayer(spellCard.getOwnerId());
|
||||
if (controller.moveCards(spell, Zone.LIBRARY, source, game) && !spell.isCopy()) {
|
||||
Player owner = game.getPlayer(spell.getCard().getOwnerId());
|
||||
if (owner != null) {
|
||||
controller.moveCardToLibraryWithInfo(spellCard, source.getSourceId(), game, Zone.STACK, true, true);
|
||||
owner.shuffleLibrary(game);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -36,7 +36,6 @@ import mage.constants.Layer;
|
|||
import mage.constants.Outcome;
|
||||
import mage.constants.SubLayer;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
@ -75,19 +74,17 @@ public class SetPowerToughnessSourceEffect extends ContinuousEffectImpl {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
MageObject mageObject = game.getObject(source.getSourceId());
|
||||
MageObject mageObject = game.getPermanentEntering(source.getSourceId());
|
||||
if (mageObject == null) {
|
||||
game.getPermanentEntering(source.getSourceId());
|
||||
if (duration.equals(Duration.Custom) || isTemporary()) {
|
||||
mageObject = game.getPermanent(source.getSourceId());
|
||||
} else {
|
||||
mageObject = game.getObject(source.getSourceId());
|
||||
}
|
||||
}
|
||||
if (mageObject == null) {
|
||||
if (duration.equals(Duration.Custom)) {
|
||||
discard();
|
||||
}
|
||||
return false;
|
||||
} else if (isTemporary()) { // it's somehow w
|
||||
if (!(mageObject instanceof Permanent)) {
|
||||
return false;
|
||||
}
|
||||
discard();
|
||||
return true;
|
||||
}
|
||||
if (amount != null) {
|
||||
int value = amount.calculate(game, source, this);
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ public class SearchLibraryPutInPlayEffect extends SearchEffect {
|
|||
if (player.searchLibrary(target, game)) {
|
||||
if (target.getTargets().size() > 0) {
|
||||
player.moveCards(new CardsImpl(target.getTargets()).getCards(game),
|
||||
Zone.BATTLEFIELD, source, game, true, false, false, null);
|
||||
Zone.BATTLEFIELD, source, game, tapped, false, false, null);
|
||||
}
|
||||
player.shuffleLibrary(game);
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ public class EntwineAbility extends StaticAbility implements OptionalAdditionalM
|
|||
if (player != null) {
|
||||
this.resetCosts();
|
||||
if (additionalCost != null) {
|
||||
if (player.chooseUse(Outcome.Benefit, new StringBuilder("Pay ").append(additionalCost.getText(false)).append(" ?").toString(), ability, game)) {
|
||||
if (player.chooseUse(Outcome.Benefit, "Pay " + additionalCost.getText(false) + " ?", ability, game)) {
|
||||
additionalCost.activate();
|
||||
for (Iterator it = ((Costs) additionalCost).iterator(); it.hasNext();) {
|
||||
Cost cost = (Cost) it.next();
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@
|
|||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
package mage.constants;
|
||||
|
||||
/**
|
||||
|
|
@ -33,5 +32,6 @@ package mage.constants;
|
|||
* @author LevelX2
|
||||
*/
|
||||
public enum SetTargetPointer {
|
||||
NONE, PLAYER, SPELL, CARD, PERMANENT;
|
||||
|
||||
NONE, PLAYER, SPELL, CARD, PERMANENT, ATTACHED_TO_CONTROLLER;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ public enum CounterType {
|
|||
DOOM("doom"),
|
||||
ELIXIR("elixir"),
|
||||
EON("eon"),
|
||||
EXPERIENCE("experience"),
|
||||
EYEBALL("eyeball"),
|
||||
FADE("fade"),
|
||||
FATE("fate"),
|
||||
|
|
|
|||
|
|
@ -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.filter.predicate.mageobject;
|
||||
|
||||
import mage.MageObject;
|
||||
import mage.filter.predicate.ObjectSourcePlayer;
|
||||
import mage.filter.predicate.ObjectSourcePlayerPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.stack.StackObject;
|
||||
import mage.target.Target;
|
||||
|
||||
/**
|
||||
* All targets that are already selected in other target definitions of the
|
||||
* source are omitted To use this predicate you have to set the targetTag of all
|
||||
* targets involved in the card constructor to a unique value (e.g. using 1,2,3
|
||||
* for three targets)
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class AnotherTargetPredicate implements ObjectSourcePlayerPredicate<ObjectSourcePlayer<MageObject>> {
|
||||
|
||||
private final int targetTag;
|
||||
|
||||
public AnotherTargetPredicate(int targetTag) {
|
||||
this.targetTag = targetTag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(ObjectSourcePlayer<MageObject> input, Game game) {
|
||||
StackObject source = game.getStack().getStackObject(input.getSourceId());
|
||||
if (source != null) {
|
||||
for (Target target : source.getStackAbility().getTargets()) {
|
||||
if (target.getTargetTag() > 0 // target is included in the target group to check
|
||||
&& target.getTargetTag() != targetTag // it's not the target of this predicate
|
||||
&& target.getTargets().contains(input.getObject().getId())) { // if the uuid already is used for another target in the group it's no allowed here
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Another target";
|
||||
}
|
||||
}
|
||||
|
|
@ -622,7 +622,8 @@ public class Spell extends StackObjImpl implements Card {
|
|||
}
|
||||
|
||||
public Spell copySpell() {
|
||||
return new Spell(this.card.copy(), this.ability.copySpell(), this.controllerId, this.fromZone);
|
||||
// replaced card.copy by copy (card content should no longer be changed)
|
||||
return new Spell(this.card, this.ability.copySpell(), this.controllerId, this.fromZone);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -1217,11 +1217,15 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
public LinkedHashMap<UUID, ActivatedAbility> getUseableActivatedAbilities(MageObject object, Zone zone, Game game) {
|
||||
LinkedHashMap<UUID, ActivatedAbility> useable = new LinkedHashMap<>();
|
||||
boolean canUse = !(object instanceof Permanent) || ((Permanent) object).canUseActivatedAbilities(game);
|
||||
ManaOptions availableMana = null;
|
||||
// ManaOptions availableMana = getManaAvailable(game); // can only be activated if mana calculation works flawless otherwise player can't play spells they could play if calculation would work correctly
|
||||
// availableMana.addMana(manaPool.getMana());
|
||||
for (Ability ability : object.getAbilities()) {
|
||||
if (canUse || ability.getAbilityType().equals(AbilityType.SPECIAL_ACTION)) {
|
||||
if (ability.getZone().match(zone)) {
|
||||
if (ability instanceof ActivatedAbility) {
|
||||
if (((ActivatedAbility) ability).canActivate(playerId, game)) {
|
||||
if (canPlay(((ActivatedAbility) ability), availableMana, object, game)) {
|
||||
// if (((ActivatedAbility) ability).canActivate(playerId, game)) {
|
||||
useable.put(ability.getId(), (ActivatedAbility) ability);
|
||||
}
|
||||
} else if (ability instanceof AlternativeSourceCosts) {
|
||||
|
|
@ -2297,6 +2301,14 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param ability
|
||||
* @param available if null, it won't be checked if enough mana is available
|
||||
* @param sourceObject
|
||||
* @param game
|
||||
* @return
|
||||
*/
|
||||
protected boolean canPlay(ActivatedAbility ability, ManaOptions available, MageObject sourceObject, Game game) {
|
||||
if (!(ability instanceof ManaAbility)) {
|
||||
ActivatedAbility copy = ability.copy();
|
||||
|
|
@ -2317,15 +2329,26 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
ManaOptions abilityOptions = copy.getManaCostsToPay().getOptions();
|
||||
if (abilityOptions.size() == 0) {
|
||||
return true;
|
||||
} else {
|
||||
for (Mana mana : abilityOptions) {
|
||||
for (Mana avail : available) {
|
||||
if (mana.enough(avail)) {
|
||||
return true;
|
||||
boolean canBeCastRegularly = true;
|
||||
if (copy instanceof SpellAbility && copy.getManaCosts().isEmpty() && copy.getCosts().isEmpty()) {
|
||||
// 117.6. Some mana costs contain no mana symbols. This represents an unpayable cost...
|
||||
// 117.6a (...) If an alternative cost is applied to an unpayable cost,
|
||||
// including an effect that allows a player to cast a spell without paying its mana cost, the alternative cost may be paid.
|
||||
canBeCastRegularly = false;
|
||||
}
|
||||
if (canBeCastRegularly) {
|
||||
ManaOptions abilityOptions = copy.getManaCostsToPay().getOptions();
|
||||
if (abilityOptions.size() == 0) {
|
||||
return true;
|
||||
} else {
|
||||
if (available == null) {
|
||||
return true;
|
||||
}
|
||||
for (Mana mana : abilityOptions) {
|
||||
for (Mana avail : available) {
|
||||
if (mana.enough(avail)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2369,6 +2392,9 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
if (manaCosts.size() == 0) {
|
||||
return true;
|
||||
} else {
|
||||
if (available == null) {
|
||||
return true;
|
||||
}
|
||||
for (Mana mana : manaCosts.getOptions()) {
|
||||
for (Mana avail : available) {
|
||||
if (mana.enough(avail)) {
|
||||
|
|
@ -3097,7 +3123,11 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
break;
|
||||
case LIBRARY:
|
||||
for (Card card : cards) {
|
||||
fromZone = game.getState().getZone(card.getId());
|
||||
if (card instanceof Spell) {
|
||||
fromZone = game.getState().getZone(((Spell) card).getSourceId());
|
||||
} else {
|
||||
fromZone = game.getState().getZone(card.getId());
|
||||
}
|
||||
boolean hideCard = fromZone.equals(Zone.HAND) || fromZone.equals(Zone.LIBRARY);
|
||||
if (moveCardToLibraryWithInfo(card, source == null ? null : source.getSourceId(), game, fromZone, true, !hideCard)) {
|
||||
successfulMovedCards.add(card);
|
||||
|
|
|
|||
|
|
@ -151,4 +151,8 @@ public interface Target extends Serializable {
|
|||
UUID getAbilityController();
|
||||
|
||||
Player getTargetController(Game game, UUID playerId);
|
||||
|
||||
int getTargetTag();
|
||||
|
||||
void setTargetTag(int tag);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,6 +70,8 @@ public abstract class TargetImpl implements Target {
|
|||
protected UUID targetController = null; // if null the ability controller is the targetController
|
||||
protected UUID abilityController = null; // only used if target controller != ability controller
|
||||
|
||||
protected int targetTag; // can be set if other target check is needed (AnotherTargetPredicate)
|
||||
|
||||
@Override
|
||||
public abstract TargetImpl copy();
|
||||
|
||||
|
|
@ -95,6 +97,7 @@ public abstract class TargetImpl implements Target {
|
|||
this.notTarget = target.notTarget;
|
||||
this.targetController = target.targetController;
|
||||
this.abilityController = target.abilityController;
|
||||
this.targetTag = target.targetTag;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -545,4 +548,20 @@ public abstract class TargetImpl implements Target {
|
|||
return requiredExplicitlySet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTargetTag() {
|
||||
return targetTag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is used to be able to check, that another target is slected within the
|
||||
* group of targets of the ability with a target tag > 0.
|
||||
*
|
||||
* @param targetTag
|
||||
*/
|
||||
@Override
|
||||
public void setTargetTag(int targetTag) {
|
||||
this.targetTag = targetTag;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,44 +1,42 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.target;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.constants.Zone;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
|
|
@ -50,7 +48,7 @@ public class TargetPermanent extends TargetObject {
|
|||
public TargetPermanent() {
|
||||
this(1, 1, new FilterPermanent(), false);
|
||||
}
|
||||
|
||||
|
||||
public TargetPermanent(FilterPermanent filter) {
|
||||
this(1, 1, filter, false);
|
||||
}
|
||||
|
|
@ -88,8 +86,8 @@ public class TargetPermanent extends TargetObject {
|
|||
// first for protection from spells or abilities (e.g. protection from colored spells, r1753)
|
||||
// second for protection from sources (e.g. protection from artifacts + equip ability)
|
||||
if (!isNotTarget()) {
|
||||
if (!permanent.canBeTargetedBy(game.getObject(source.getId()), controllerId, game) ||
|
||||
!permanent.canBeTargetedBy(game.getObject(source.getSourceId()), controllerId, game)) {
|
||||
if (!permanent.canBeTargetedBy(game.getObject(source.getId()), controllerId, game)
|
||||
|| !permanent.canBeTargetedBy(game.getObject(source.getSourceId()), controllerId, game)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -117,7 +115,8 @@ public class TargetPermanent extends TargetObject {
|
|||
/**
|
||||
* Checks if there are enough {@link Permanent} that can be chosen.
|
||||
*
|
||||
* Takes into account notTarget parameter, in case it's true doesn't check for protection, shroud etc.
|
||||
* Takes into account notTarget parameter, in case it's true doesn't check
|
||||
* for protection, shroud etc.
|
||||
*
|
||||
* @param sourceId the target event source
|
||||
* @param sourceControllerId controller of the target event source
|
||||
|
|
@ -132,7 +131,7 @@ public class TargetPermanent extends TargetObject {
|
|||
}
|
||||
int count = 0;
|
||||
MageObject targetSource = game.getObject(sourceId);
|
||||
for (Permanent permanent: game.getBattlefield().getActivePermanents(filter, sourceControllerId, sourceId, game)) {
|
||||
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, sourceControllerId, sourceId, game)) {
|
||||
if (!targets.containsKey(permanent.getId())) {
|
||||
if (notTarget || permanent.canBeTargetedBy(targetSource, sourceControllerId, game)) {
|
||||
count++;
|
||||
|
|
@ -146,9 +145,10 @@ public class TargetPermanent extends TargetObject {
|
|||
}
|
||||
|
||||
/**
|
||||
* Checks if there are enough {@link Permanent} that can be selected. Should not be used
|
||||
* for Ability targets since this does not check for protection, shroud etc.
|
||||
*
|
||||
* Checks if there are enough {@link Permanent} that can be selected. Should
|
||||
* not be used for Ability targets since this does not check for protection,
|
||||
* shroud etc.
|
||||
*
|
||||
* @param sourceControllerId - controller of the select event
|
||||
* @param game
|
||||
* @return - true if enough valid {@link Permanent} exist
|
||||
|
|
@ -162,7 +162,7 @@ public class TargetPermanent extends TargetObject {
|
|||
return true;
|
||||
}
|
||||
int count = 0;
|
||||
for (Permanent permanent: game.getBattlefield().getActivePermanents(filter, sourceControllerId, game)) {
|
||||
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, sourceControllerId, game)) {
|
||||
if (!targets.containsKey(permanent.getId())) {
|
||||
count++;
|
||||
if (count >= remainingTargets) {
|
||||
|
|
@ -177,7 +177,7 @@ public class TargetPermanent extends TargetObject {
|
|||
public Set<UUID> possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) {
|
||||
Set<UUID> possibleTargets = new HashSet<>();
|
||||
MageObject targetSource = game.getObject(sourceId);
|
||||
for (Permanent permanent: game.getBattlefield().getActivePermanents(filter, sourceControllerId, sourceId, game)) {
|
||||
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, sourceControllerId, sourceId, game)) {
|
||||
if (!targets.containsKey(permanent.getId())) {
|
||||
if (notTarget || permanent.canBeTargetedBy(targetSource, sourceControllerId, game)) {
|
||||
possibleTargets.add(permanent.getId());
|
||||
|
|
@ -190,7 +190,7 @@ public class TargetPermanent extends TargetObject {
|
|||
@Override
|
||||
public Set<UUID> possibleTargets(UUID sourceControllerId, Game game) {
|
||||
Set<UUID> possibleTargets = new HashSet<>();
|
||||
for (Permanent permanent: game.getBattlefield().getActivePermanents(filter, sourceControllerId, game)) {
|
||||
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, sourceControllerId, game)) {
|
||||
if (!targets.containsKey(permanent.getId())) {
|
||||
possibleTargets.add(permanent.getId());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ Classic Sixth Edition|classicsixthedition|
|
|||
Coldsnap|coldsnap|
|
||||
Commander 2013 Edition|commander2013|
|
||||
Commander 2014 Edition|commander2014|
|
||||
Commander 2015|commander2015|
|
||||
Conflux|conflux|
|
||||
Dark Ascension|darkascension|
|
||||
Darksteel|darksteel|
|
||||
|
|
|
|||
|
|
@ -27631,3 +27631,5 @@ Swamp|Battle for Zendikar|262|L||Basic Land - Swamp|||<i>({t}: Add {B} to your m
|
|||
Swamp|Battle for Zendikar|264|L||Basic Land - Swamp|||<i>({t}: Add {B} to your mana pool.)</i>|
|
||||
Swamp|Battle for Zendikar|260|L||Basic Land - Swamp|||<i>({t}: Add {B} to your mana pool.)</i>|
|
||||
Swamp|Battle for Zendikar|261|L||Basic Land - Swamp|||<i>({t}: Add {B} to your mana pool.)</i>|
|
||||
Eternal Witness|Commander 2015|183|U|{1}{G}{G}|Creature - Human Shaman|2|1|When Eternal Witness enters the battlefield, you may return target card from your graveyard to your hand.|
|
||||
Kalemne, Disciple of Iroas|Commander 2015|999|M|{2}{R}{W}|Legendary Creature - Giant Soldier|3|3|Double strike, vigilance$Whenever you cast a creature spell with converted mana cost 5 or greater, you get an experience counter.$Kalemne, Disciple of Iroas gets +1/+1 for each experience counter you have.|
|
||||
|
|
@ -25,6 +25,7 @@ Chronicles|CHR|
|
|||
Clash Pack|CLASH|
|
||||
Commander 2013 Edition|C13|
|
||||
Commander 2014 Edition|C14|
|
||||
Commander 2015|C15|
|
||||
Conflux|CON|
|
||||
Coldsnap|CSP|
|
||||
Dark Ascension|DKA|
|
||||
|
|
|
|||
|
|
@ -36,6 +36,9 @@ git log 7650f53dee0b4d480d2a63befed72b6c8197e752..head --diff-filter=A --name-st
|
|||
since 1.4.4.v8
|
||||
git log 8c7dc7b2da3630b6dfec1390854fa2be11631c79..head --diff-filter=A --name-status | sed -ne "s/^A[^u]Mage.Sets\/src\/mage\/sets\///p" | sort > added_cards.txt
|
||||
|
||||
since 1.4.4.v9
|
||||
git log 1b71f505064b82893003207fc29954de533fbed5..head --diff-filter=A --name-status | sed -ne "s/^A[^u]Mage.Sets\/src\/mage\/sets\///p" | sort > added_cards.txt
|
||||
|
||||
3. Copy added_cards.txt to trunk\Utils folder
|
||||
4. Run script:
|
||||
> perl extract_in_wiki_format.perl
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue