Merge origin/master

This commit is contained in:
LevelX2 2016-08-08 16:29:58 +02:00
commit 47fb2c1ac5
71 changed files with 1992 additions and 497 deletions

View file

@ -294,7 +294,7 @@ public class TournamentController {
TournamentPlayer player = tournament.getPlayer(playerId); TournamentPlayer player = tournament.getPlayer(playerId);
if (player != null && !player.hasQuit()) { if (player != null && !player.hasQuit()) {
tournamentSessions.get(playerId).submitDeck(deck); tournamentSessions.get(playerId).submitDeck(deck);
ChatManager.getInstance().broadcast(chatId, "", player.getPlayer().getLogName() + " has submitted his tournament deck", MessageColor.BLACK, true, MessageType.STATUS, SoundToPlay.PlayerSubmittedDeck); ChatManager.getInstance().broadcast(chatId, "", player.getPlayer().getLogName() + " has submitted his or her tournament deck", MessageColor.BLACK, true, MessageType.STATUS, SoundToPlay.PlayerSubmittedDeck);
} }
} }
} }

View file

@ -144,22 +144,20 @@ class KusariGamaDamageEffect extends OneShotEffect {
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
Integer damage = (Integer) this.getValue("damageAmount"); Integer damage = (Integer) this.getValue("damageAmount");
if (damage != null && damage.intValue() > 0) { if (damage != null && damage > 0) {
UUID damagedCreatureId = (UUID) this.getValue("damagedCreatureId"); UUID damagedCreatureId = (UUID) this.getValue("damagedCreatureId");
Permanent creature = game.getPermanent(damagedCreatureId); Permanent creature = game.getPermanent(damagedCreatureId);
if (creature == null) { if (creature == null) {
creature = (Permanent) game.getLastKnownInformation(damagedCreatureId, Zone.BATTLEFIELD); creature = (Permanent) game.getLastKnownInformation(damagedCreatureId, Zone.BATTLEFIELD);
} }
if (creature != null) { if (creature != null) {
for (UUID blockerId : game.getCombat().getBlockers()) { for (Permanent permanent : game.getBattlefield().getAllActivePermanents(new FilterCreaturePermanent(), creature.getControllerId(), game)) {
if (!blockerId.equals(damagedCreatureId)) { if (!permanent.getId().equals(damagedCreatureId)) {
Permanent blockingCreature = game.getPermanent(blockerId); permanent.damage(damage, source.getSourceId(), game, false, true);
if (blockingCreature != null && blockingCreature.getControllerId().equals(creature.getControllerId())) {
blockingCreature.damage(damage, source.getSourceId(), game, false, true);
}
} }
} }
} }
return true;
} }
return false; return false;
} }

View file

@ -158,8 +158,8 @@ class MarathWillOfTheWildCreateTokenEffect extends OneShotEffect {
if (player != null) { if (player != null) {
int amount = new ManacostVariableValue().calculate(game, source, this); int amount = new ManacostVariableValue().calculate(game, source, this);
Token token = new MarathWillOfTheWildElementalToken(); Token token = new MarathWillOfTheWildElementalToken();
token.getPower().initValue(amount); token.getPower().modifyBaseValue(amount);
token.getToughness().initValue(amount); token.getToughness().modifyBaseValue(amount);
token.putOntoBattlefield(1, game, source.getSourceId(), source.getControllerId()); token.putOntoBattlefield(1, game, source.getSourceId(), source.getControllerId());
return true; return true;
} }

View file

@ -27,10 +27,8 @@
*/ */
package mage.sets.darkascension; package mage.sets.darkascension;
import java.util.UUID;
import mage.ConditionalMana; import mage.ConditionalMana;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.MageObject; import mage.MageObject;
import mage.Mana; import mage.Mana;
import mage.abilities.Ability; import mage.abilities.Ability;
@ -40,9 +38,11 @@ import mage.abilities.keyword.FlashbackAbility;
import mage.abilities.mana.ConditionalAnyColorManaAbility; import mage.abilities.mana.ConditionalAnyColorManaAbility;
import mage.abilities.mana.builder.ConditionalManaBuilder; import mage.abilities.mana.builder.ConditionalManaBuilder;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.game.Game; import mage.game.Game;
import mage.game.stack.Spell;
import java.util.UUID;
/** /**
* *
@ -72,6 +72,7 @@ public class AltarOfTheLost extends CardImpl {
} }
class AltarOfTheLostManaBuilder extends ConditionalManaBuilder { class AltarOfTheLostManaBuilder extends ConditionalManaBuilder {
@Override @Override
public ConditionalMana build(Object... options) { public ConditionalMana build(Object... options) {
return new AltarOfTheLostConditionalMana(this.mana); return new AltarOfTheLostConditionalMana(this.mana);
@ -93,11 +94,12 @@ class AltarOfTheLostConditionalMana extends ConditionalMana {
} }
class AltarOfTheLostManaCondition implements Condition { class AltarOfTheLostManaCondition implements Condition {
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
MageObject object = game.getObject(source.getSourceId()); MageObject object = game.getObject(source.getSourceId());
if (object != null && game.getState().getZone(object.getId()) == Zone.GRAVEYARD) { if (object instanceof Spell && ((Spell) object).getFromZone().equals(Zone.GRAVEYARD)) {
for (Ability ability: object.getAbilities()) { for (Ability ability : ((Spell) object).getAbilities(game)) {
if (ability instanceof FlashbackAbility) { if (ability instanceof FlashbackAbility) {
return true; return true;
} }

View file

@ -113,8 +113,8 @@ class WireflyToken extends Token {
WireflyToken() { WireflyToken() {
super("Wirefly", "2/2 colorless Insect artifact creature token named Wirefly"); super("Wirefly", "2/2 colorless Insect artifact creature token named Wirefly");
this.setOriginalExpansionSetCode("DST"); this.setOriginalExpansionSetCode("DST");
this.getPower().initValue(2); this.getPower().modifyBaseValue(2);
this.getToughness().initValue(2); this.getToughness().modifyBaseValue(2);
this.getSubtype().add("Insect"); this.getSubtype().add("Insect");
this.getCardType().add(CardType.ARTIFACT); this.getCardType().add(CardType.ARTIFACT);
this.getCardType().add(CardType.CREATURE); this.getCardType().add(CardType.CREATURE);

View file

@ -0,0 +1,120 @@
/*
* 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.eighthedition;
import java.util.UUID;
import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.Cost;
import mage.abilities.costs.CostImpl;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.DestroyTargetEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.ColorPredicate;
import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetCreaturePermanent;
/**
*
* @author choiseul11
*/
public class MurderousBetrayal extends CardImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nonblack creature");
static {
filter.add(Predicates.not(new ColorPredicate(ObjectColor.BLACK)));
}
public MurderousBetrayal(UUID ownerId) {
super(ownerId, 147, "Murderous Betrayal", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{B}{B}{B}");
this.expansionSetCode = "8ED";
// {B}{B}, Pay half your life, rounded up: Destroy target nonblack creature. It can't be regenerated.
Effect effect = new DestroyTargetEffect(true);
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new MurderousBetrayalCost());
ability.addCost(new ManaCostsImpl("{B}{B}"));
ability.addTarget(new TargetCreaturePermanent(filter));
this.addAbility(ability);
}
public MurderousBetrayal(final MurderousBetrayal card) {
super(card);
}
@Override
public MurderousBetrayal copy() {
return new MurderousBetrayal(this);
}
}
class MurderousBetrayalCost extends CostImpl {
MurderousBetrayalCost() {
this.text = "Pay half your life, rounded up";
}
MurderousBetrayalCost(MurderousBetrayalCost cost) {
super(cost);
}
@Override
public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) {
Player controller = game.getPlayer(controllerId);
return controller != null && (controller.getLife() < 1 || controller.canPayLifeCost());
}
@Override
public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana, Cost costToPay) {
Player controller = game.getPlayer(controllerId);
if (controller != null) {
int currentLife = controller.getLife();
int lifeToPay = (currentLife + currentLife % 2) / 2; // Divide by two and round up.
if (lifeToPay < 0) {
this.paid = true;
} else {
this.paid = (controller.loseLife(lifeToPay, game) == lifeToPay);
}
return this.paid;
}
return false;
}
@Override
public MurderousBetrayalCost copy() {
return new MurderousBetrayalCost(this);
}
}

View file

@ -106,10 +106,7 @@ class IdentityThiefAbility extends TriggeredAbilityImpl {
@Override @Override
public boolean checkTrigger(GameEvent event, Game game) { public boolean checkTrigger(GameEvent event, Game game) {
if (event.getSourceId().equals(this.getSourceId())) { return event.getSourceId().equals(this.getSourceId());
return true;
}
return false;
} }
@Override @Override
@ -141,7 +138,11 @@ class IdentityThiefEffect extends OneShotEffect {
Player controller = game.getPlayer(source.getControllerId()); Player controller = game.getPlayer(source.getControllerId());
Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId()); Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId());
if (controller != null && permanent != null && sourcePermanent != null) { if (controller != null && permanent != null && sourcePermanent != null) {
CopyEffect copyEffect = new CopyEffect(Duration.EndOfTurn, permanent, source.getSourceId()); Permanent permanentReset = permanent.copy();
permanentReset.getCounters().clear();
permanentReset.getPower().resetToBaseValue();
permanentReset.getToughness().resetToBaseValue();
CopyEffect copyEffect = new CopyEffect(Duration.EndOfTurn, permanentReset, source.getSourceId());
if (controller.moveCardToExileWithInfo(permanent, source.getSourceId(), sourcePermanent.getIdName(), source.getSourceId(), game, Zone.BATTLEFIELD, true)) { if (controller.moveCardToExileWithInfo(permanent, source.getSourceId(), sourcePermanent.getIdName(), source.getSourceId(), game, Zone.BATTLEFIELD, true)) {
// Copy exiled permanent // Copy exiled permanent
game.addEffect(copyEffect, source); game.addEffect(copyEffect, source);

View file

@ -34,7 +34,7 @@ import mage.abilities.common.UnattachedTriggeredAbility;
import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.Effect; import mage.abilities.effects.Effect;
import mage.abilities.effects.common.DontUntapInControllersNextUntapStepSourceEffect; import mage.abilities.effects.common.DontUntapInControllersNextUntapStepSourceEffect;
import mage.abilities.effects.common.SacrificeEquippedEffect; import mage.abilities.effects.common.SacrificeTargetEffect;
import mage.abilities.effects.common.continuous.BoostEquippedEffect; import mage.abilities.effects.common.continuous.BoostEquippedEffect;
import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect;
import mage.abilities.keyword.EquipAbility; import mage.abilities.keyword.EquipAbility;
@ -68,7 +68,7 @@ public class StitchersGraft extends CardImpl {
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect)); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect));
// Whenever Stitcher's Graft becomes unattached from a permanent, sacrifice that permanent. // Whenever Stitcher's Graft becomes unattached from a permanent, sacrifice that permanent.
effect = new SacrificeEquippedEffect(); effect = new SacrificeTargetEffect();
effect.setText("sacrifice that permanent"); effect.setText("sacrifice that permanent");
this.addAbility(new UnattachedTriggeredAbility(effect, false)); this.addAbility(new UnattachedTriggeredAbility(effect, false));

View file

@ -27,8 +27,12 @@
*/ */
package mage.sets.eldritchmoon; package mage.sets.eldritchmoon;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID; import java.util.UUID;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbility; import mage.abilities.TriggeredAbility;
import mage.abilities.common.BeginningOfYourEndStepTriggeredAbility; import mage.abilities.common.BeginningOfYourEndStepTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
@ -36,7 +40,6 @@ import mage.abilities.condition.CompoundCondition;
import mage.abilities.condition.Condition; import mage.abilities.condition.Condition;
import mage.abilities.condition.InvertCondition; import mage.abilities.condition.InvertCondition;
import mage.abilities.condition.common.AttachedCondition; import mage.abilities.condition.common.AttachedCondition;
import mage.abilities.condition.common.WatcherCondition;
import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.decorator.ConditionalTriggeredAbility; import mage.abilities.decorator.ConditionalTriggeredAbility;
import mage.abilities.effects.common.SacrificeEquippedEffect; import mage.abilities.effects.common.SacrificeEquippedEffect;
@ -50,6 +53,7 @@ import mage.game.events.GameEvent;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.watchers.Watcher; import mage.watchers.Watcher;
/** /**
* *
* @author Quercitron * @author Quercitron
@ -67,12 +71,12 @@ public class ThirstingAxe extends CardImpl {
// At the beginning of your end step, if equipped creature didn't deal combat damage to a creature this turn, sacrifice it. // At the beginning of your end step, if equipped creature didn't deal combat damage to a creature this turn, sacrifice it.
TriggeredAbility ability = new BeginningOfYourEndStepTriggeredAbility(new SacrificeEquippedEffect(), false); TriggeredAbility ability = new BeginningOfYourEndStepTriggeredAbility(new SacrificeEquippedEffect(), false);
Condition condition = new CompoundCondition( Condition condition = new CompoundCondition(
new AttachedCondition(), AttachedCondition.getInstance(),
new InvertCondition(new WatcherCondition(CombatDamageToCreatureByEquippedWatcher.BASIC_KEY, WatcherScope.CARD))); new InvertCondition(new EquippedDealtCombatDamageToCreatureCondition()));
String triggeredAbilityText = "At the beginning of your end step, if equipped creature " + String triggeredAbilityText = "At the beginning of your end step, if equipped creature " +
"didn't deal combat damage to a creature this turn, sacrifice it."; "didn't deal combat damage to a creature this turn, sacrifice it.";
ConditionalTriggeredAbility sacrificeTriggeredAbility = new ConditionalTriggeredAbility(ability, condition, triggeredAbilityText); ConditionalTriggeredAbility sacrificeTriggeredAbility = new ConditionalTriggeredAbility(ability, condition, triggeredAbilityText);
this.addAbility(sacrificeTriggeredAbility, new CombatDamageToCreatureByEquippedWatcher()); this.addAbility(sacrificeTriggeredAbility, new CombatDamageToCreatureWatcher());
// Equip {2} // Equip {2}
this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(2))); this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(2)));
@ -88,34 +92,62 @@ public class ThirstingAxe extends CardImpl {
} }
} }
class CombatDamageToCreatureByEquippedWatcher extends Watcher { class EquippedDealtCombatDamageToCreatureCondition implements Condition {
public final static String BASIC_KEY = "CombatDamageToCreatureByEquippedWatcher"; @Override
public boolean apply(Game game, Ability source) {
public CombatDamageToCreatureByEquippedWatcher() { Permanent equipment = game.getPermanent(source.getSourceId());
super(BASIC_KEY, WatcherScope.CARD); if (equipment != null && equipment.getAttachedTo() != null) {
CombatDamageToCreatureWatcher watcher =
(CombatDamageToCreatureWatcher) game.getState().getWatchers().get(CombatDamageToCreatureWatcher.BASIC_KEY);
return watcher.dealtDamage(equipment.getAttachedTo(), equipment.getAttachedToZoneChangeCounter(), game);
}
return false;
} }
public CombatDamageToCreatureByEquippedWatcher(final CombatDamageToCreatureByEquippedWatcher watcher) { }
class CombatDamageToCreatureWatcher extends Watcher {
// which objects dealt combat damage to creature during the turn
public final Set<MageObjectReference> dealtCombatDamageToCreature;
public final static String BASIC_KEY = "CombatDamageToCreatureWatcher";
public CombatDamageToCreatureWatcher() {
super(BASIC_KEY, WatcherScope.GAME);
dealtCombatDamageToCreature = new HashSet<>();
}
public CombatDamageToCreatureWatcher(final CombatDamageToCreatureWatcher watcher) {
super(watcher); super(watcher);
dealtCombatDamageToCreature = new HashSet<>(watcher.dealtCombatDamageToCreature);
} }
@Override @Override
public CombatDamageToCreatureByEquippedWatcher copy() { public CombatDamageToCreatureWatcher copy() {
return new CombatDamageToCreatureByEquippedWatcher(this); return new CombatDamageToCreatureWatcher(this);
} }
@Override @Override
public void watch(GameEvent event, Game game) { public void watch(GameEvent event, Game game) {
if (event.getType() == GameEvent.EventType.DAMAGED_CREATURE) { if (event.getType() == GameEvent.EventType.DAMAGED_CREATURE) {
Permanent equipment = game.getPermanent(this.getSourceId());
if (equipment != null && equipment.getAttachedTo() != null) {
if (equipment.getAttachedTo().equals(event.getSourceId())) {
if (((DamagedCreatureEvent) event).isCombatDamage()) { if (((DamagedCreatureEvent) event).isCombatDamage()) {
condition = true; MageObjectReference damageSource = new MageObjectReference(event.getSourceId(), game);
dealtCombatDamageToCreature.add(damageSource);
} }
} }
} }
@Override
public void reset() {
super.reset();
dealtCombatDamageToCreature.clear();
} }
public boolean dealtDamage(UUID objectId, int zoneChangeCounter, Game game) {
MageObjectReference reference = new MageObjectReference(objectId, zoneChangeCounter, game);
return dealtCombatDamageToCreature.contains(reference);
} }
} }

View file

@ -33,14 +33,11 @@ import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.continuous.SetPowerToughnessSourceEffect;
import mage.abilities.keyword.DefenderAbility; import mage.abilities.keyword.DefenderAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.constants.Rarity; import mage.constants.Rarity;
import mage.constants.SubLayer;
import mage.constants.Zone; import mage.constants.Zone;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
@ -108,7 +105,9 @@ class TreeOfPerditionEffect extends OneShotEffect {
return false; return false;
} }
opponent.setLife(amount, game); opponent.setLife(amount, game);
game.addEffect(new SetPowerToughnessSourceEffect(Integer.MIN_VALUE, life, Duration.Custom, SubLayer.SetPT_7b), source); perm.getPower().modifyBaseValue(life);
perm.getToughness().modifyBaseValue(life);
// game.addEffect(new SetPowerToughnessSourceEffect(Integer.MIN_VALUE, life, Duration.Custom, SubLayer.SetPT_7b), source);
return true; return true;
} }
} }

View file

@ -82,8 +82,8 @@ class CamaridToken extends Token {
CamaridToken() { CamaridToken() {
super("Camarid", "1/1 blue Camarid creature tokens"); super("Camarid", "1/1 blue Camarid creature tokens");
this.setOriginalExpansionSetCode("FEM"); this.setOriginalExpansionSetCode("FEM");
this.getPower().initValue(1); this.getPower().modifyBaseValue(1);
this.getToughness().initValue(1); this.getToughness().modifyBaseValue(1);
this.color.setBlue(true); this.color.setBlue(true);
this.getSubtype().add("Camarid"); this.getSubtype().add("Camarid");
this.getCardType().add(CardType.CREATURE); this.getCardType().add(CardType.CREATURE);

View file

@ -31,7 +31,7 @@ import java.util.UUID;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.common.UnattachedTriggeredAbility; import mage.abilities.common.UnattachedTriggeredAbility;
import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.common.SacrificeEquippedEffect; import mage.abilities.effects.common.SacrificeTargetEffect;
import mage.abilities.effects.common.continuous.BoostEquippedEffect; import mage.abilities.effects.common.continuous.BoostEquippedEffect;
import mage.abilities.keyword.EquipAbility; import mage.abilities.keyword.EquipAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
@ -55,7 +55,7 @@ public class GraftedWargear extends CardImpl {
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(3, 2))); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(3, 2)));
// Whenever Grafted Wargear becomes unattached from a permanent, sacrifice that permanent. // Whenever Grafted Wargear becomes unattached from a permanent, sacrifice that permanent.
this.addAbility(new UnattachedTriggeredAbility(new SacrificeEquippedEffect(), false)); this.addAbility(new UnattachedTriggeredAbility(new SacrificeTargetEffect(), false));
// Equip {0} // Equip {0}
this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(0))); this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(0)));

View file

@ -33,7 +33,6 @@ import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ReplacementEffectImpl; import mage.abilities.effects.ReplacementEffectImpl;
import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
import mage.abilities.effects.common.continuous.SetPowerToughnessSourceEffect;
import mage.abilities.keyword.DefenderAbility; import mage.abilities.keyword.DefenderAbility;
import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
@ -43,7 +42,6 @@ import mage.constants.CardType;
import mage.constants.Duration; import mage.constants.Duration;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.constants.Rarity; import mage.constants.Rarity;
import mage.constants.SubLayer;
import mage.constants.Zone; import mage.constants.Zone;
import mage.game.Game; import mage.game.Game;
import mage.game.events.EntersTheBattlefieldEvent; import mage.game.events.EntersTheBattlefieldEvent;
@ -152,7 +150,9 @@ class PrimalPlasmaReplacementEffect extends ReplacementEffectImpl {
game.addEffect(new GainAbilitySourceEffect(DefenderAbility.getInstance(), Duration.Custom), source); game.addEffect(new GainAbilitySourceEffect(DefenderAbility.getInstance(), Duration.Custom), source);
break; break;
} }
game.addEffect(new SetPowerToughnessSourceEffect(power, toughness, Duration.Custom, SubLayer.SetPT_7b), source); permanent.getPower().modifyBaseValue(power);
permanent.getToughness().modifyBaseValue(toughness);
// game.addEffect(new SetPowerToughnessSourceEffect(power, toughness, Duration.Custom, SubLayer.SetPT_7b), source);
} }
return false; return false;

View file

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

View file

@ -95,8 +95,8 @@ class MimingSlimeEffect extends OneShotEffect {
} }
} }
OozeToken oozeToken = new OozeToken(); OozeToken oozeToken = new OozeToken();
oozeToken.getPower().initValue(amount); oozeToken.getPower().modifyBaseValue(amount);
oozeToken.getToughness().initValue(amount); oozeToken.getToughness().modifyBaseValue(amount);
oozeToken.putOntoBattlefield(1, game, source.getSourceId(), source.getControllerId()); oozeToken.putOntoBattlefield(1, game, source.getSourceId(), source.getControllerId());
return true; return true;
} }

View file

@ -101,8 +101,8 @@ class OozeFluxCreateTokenEffect extends OneShotEffect {
} }
Token tokenCopy = token.copy(); Token tokenCopy = token.copy();
tokenCopy.getAbilities().newId(); tokenCopy.getAbilities().newId();
tokenCopy.getPower().initValue(xValue); tokenCopy.getPower().modifyBaseValue(xValue);
tokenCopy.getToughness().initValue(xValue); tokenCopy.getToughness().modifyBaseValue(xValue);
tokenCopy.putOntoBattlefield(1, game, source.getSourceId(), source.getControllerId()); tokenCopy.putOntoBattlefield(1, game, source.getSourceId(), source.getControllerId());
return true; return true;
} }

View file

@ -91,8 +91,8 @@ class SkeletonToken extends Token {
SkeletonToken() { SkeletonToken() {
super("Skeleton", "1/1 black Skeleton creature token onto the battlefield. It has \"{B}: Regenerate this creature.\""); super("Skeleton", "1/1 black Skeleton creature token onto the battlefield. It has \"{B}: Regenerate this creature.\"");
this.setOriginalExpansionSetCode("HML"); this.setOriginalExpansionSetCode("HML");
this.getPower().initValue(1); this.getPower().modifyBaseValue(1);
this.getToughness().initValue(1); this.getToughness().modifyBaseValue(1);
this.color.setBlack(true); this.color.setBlack(true);
this.getSubtype().add("Skeleton"); this.getSubtype().add("Skeleton");
this.getCardType().add(CardType.CREATURE); this.getCardType().add(CardType.CREATURE);

View file

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

View file

@ -0,0 +1,77 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.iceage;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.OnEventTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
import mage.abilities.effects.common.SacrificeSourceEffect;
import mage.abilities.effects.common.SacrificeTargetEffect;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.game.events.GameEvent;
import mage.target.common.TargetControlledCreaturePermanent;
/**
*
* @author choiseul11
*/
public class CelestialSword extends CardImpl {
public CelestialSword(UUID ownerId) {
super(ownerId, 289, "Celestial Sword", Rarity.RARE, new CardType[]{CardType.ARTIFACT}, "{6}");
this.expansionSetCode = "ICE";
// {3}, {tap}: Target creature you control gets +3/+3 until end of turn. Its controller sacrifices it at the beginning of the next end step.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostTargetEffect(3, 3, Duration.EndOfTurn), new GenericManaCost(3));
ability.addCost(new TapSourceCost());
ability.addTarget(new TargetControlledCreaturePermanent());
ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new SacrificeTargetEffect())));
this.addAbility(ability);
}
public CelestialSword(final CelestialSword card) {
super(card);
}
@Override
public CelestialSword copy() {
return new CelestialSword(this);
}
}

View file

@ -99,7 +99,11 @@ class EssenceOfTheWildEffect extends ReplacementEffectImpl {
public boolean replaceEvent(GameEvent event, Ability source, Game game) { public boolean replaceEvent(GameEvent event, Ability source, Game game) {
Permanent sourceObject = game.getPermanentOrLKIBattlefield(source.getSourceId()); Permanent sourceObject = game.getPermanentOrLKIBattlefield(source.getSourceId());
if (sourceObject != null) { if (sourceObject != null) {
game.addEffect(new CopyEffect(Duration.Custom, sourceObject, event.getTargetId()), source); Permanent permanentReset = sourceObject.copy();
permanentReset.getCounters().clear();
permanentReset.getPower().resetToBaseValue();
permanentReset.getToughness().resetToBaseValue();
game.addEffect(new CopyEffect(Duration.Custom, permanentReset, event.getTargetId()), source);
} }
return false; return false;
} }

View file

@ -80,7 +80,6 @@ public class PharikaGodOfAffliction extends CardImpl {
ability.addTarget(target); ability.addTarget(target);
this.addAbility(ability); this.addAbility(ability);
} }
public PharikaGodOfAffliction(final PharikaGodOfAffliction card) { public PharikaGodOfAffliction(final PharikaGodOfAffliction card) {
@ -132,15 +131,13 @@ class PharikaExileEffect extends OneShotEffect {
class PharikaSnakeToken extends Token { class PharikaSnakeToken extends Token {
public PharikaSnakeToken() { public PharikaSnakeToken() {
super("Snake", "1/1 black and green Snake enchantment creature token with deathtouch"); super("Snake", "1/1 black and green Snake enchantment creature token with deathtouch", 1, 1);
this.setOriginalExpansionSetCode("JOU"); this.setOriginalExpansionSetCode("JOU");
cardType.add(CardType.ENCHANTMENT); cardType.add(CardType.ENCHANTMENT);
cardType.add(CardType.CREATURE); cardType.add(CardType.CREATURE);
subtype.add("Snake"); subtype.add("Snake");
color.setBlack(true); color.setBlack(true);
color.setGreen(true); color.setGreen(true);
power.setValue(1);
toughness.setValue(1);
this.addAbility(DeathtouchAbility.getInstance()); this.addAbility(DeathtouchAbility.getInstance());
} }
} }

View file

@ -32,11 +32,12 @@ import mage.MageInt;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.Effect; import mage.abilities.effects.Effect;
import mage.abilities.effects.common.combat.CanAttackOnlyAloneEffect; import mage.abilities.effects.common.combat.CantAttackAloneAttachedEffect;
import mage.abilities.effects.common.continuous.BoostEnchantedEffect; import mage.abilities.effects.common.continuous.BoostEnchantedEffect;
import mage.abilities.keyword.BestowAbility; import mage.abilities.keyword.BestowAbility;
import mage.abilities.keyword.CantAttackAloneAbility; import mage.abilities.keyword.CantAttackAloneAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.constants.AttachmentType;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Duration; import mage.constants.Duration;
import mage.constants.Rarity; import mage.constants.Rarity;
@ -65,7 +66,7 @@ public class SightlessBrawler extends CardImpl {
Effect effect = new BoostEnchantedEffect(3, 2, Duration.WhileOnBattlefield); Effect effect = new BoostEnchantedEffect(3, 2, Duration.WhileOnBattlefield);
effect.setText("Enchanted creature gets +3/+2"); effect.setText("Enchanted creature gets +3/+2");
Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, effect); Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, effect);
effect = new CanAttackOnlyAloneEffect(); effect = new CantAttackAloneAttachedEffect(AttachmentType.AURA);
effect.setText("and can't attack alone"); effect.setText("and can't attack alone");
ability.addEffect(effect); ability.addEffect(effect);
this.addAbility(ability); this.addAbility(ability);

View file

@ -134,8 +134,8 @@ class NissaSageAnimistToken extends Token {
super("Ashaya, the Awoken World", "legendary 4/4 green Elemental creature token named Ashaya, the Awoken World"); super("Ashaya, the Awoken World", "legendary 4/4 green Elemental creature token named Ashaya, the Awoken World");
this.setOriginalExpansionSetCode("ORI"); this.setOriginalExpansionSetCode("ORI");
this.getSupertype().add("Legendary"); this.getSupertype().add("Legendary");
this.getPower().initValue(4); this.getPower().modifyBaseValue(4);
this.getToughness().initValue(4); this.getToughness().modifyBaseValue(4);
this.color.setGreen(true); this.color.setGreen(true);
this.getSubtype().add("Elemental"); this.getSubtype().add("Elemental");
this.getCardType().add(CardType.CREATURE); this.getCardType().add(CardType.CREATURE);

View file

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

View file

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

View file

@ -81,8 +81,8 @@ public class PhyrexianRebirth extends CardImpl {
count += permanent.destroy(source.getSourceId(), game, false) ? 1 : 0; count += permanent.destroy(source.getSourceId(), game, false) ? 1 : 0;
} }
HorrorToken horrorToken = new HorrorToken(); HorrorToken horrorToken = new HorrorToken();
horrorToken.getPower().initValue(count); horrorToken.getPower().modifyBaseValue(count);
horrorToken.getToughness().initValue(count); horrorToken.getToughness().modifyBaseValue(count);
horrorToken.putOntoBattlefield(1, game, source.getSourceId(), source.getControllerId()); horrorToken.putOntoBattlefield(1, game, source.getSourceId(), source.getControllerId());
return true; return true;
} }

View file

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

View file

@ -74,8 +74,8 @@ class CatWarriorToken extends Token {
CatWarriorToken() { CatWarriorToken() {
super("Cat Warrior", "2/2 green Cat Warrior creature token with forestwalk"); super("Cat Warrior", "2/2 green Cat Warrior creature token with forestwalk");
this.setOriginalExpansionSetCode("PLC"); this.setOriginalExpansionSetCode("PLC");
this.getPower().initValue(2); this.getPower().modifyBaseValue(2);
this.getToughness().initValue(2); this.getToughness().modifyBaseValue(2);
this.color.setGreen(true); this.color.setGreen(true);
this.getSubtype().add("Cat"); this.getSubtype().add("Cat");
this.getSubtype().add("Warrior"); this.getSubtype().add("Warrior");

View file

@ -33,7 +33,6 @@ import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ReplacementEffectImpl; import mage.abilities.effects.ReplacementEffectImpl;
import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
import mage.abilities.effects.common.continuous.SetPowerToughnessSourceEffect;
import mage.abilities.keyword.DefenderAbility; import mage.abilities.keyword.DefenderAbility;
import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
@ -43,7 +42,6 @@ import mage.constants.CardType;
import mage.constants.Duration; import mage.constants.Duration;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.constants.Rarity; import mage.constants.Rarity;
import mage.constants.SubLayer;
import mage.constants.Zone; import mage.constants.Zone;
import mage.game.Game; import mage.game.Game;
import mage.game.events.EntersTheBattlefieldEvent; import mage.game.events.EntersTheBattlefieldEvent;
@ -153,7 +151,9 @@ class PrimalPlasmaReplacementEffect extends ReplacementEffectImpl {
game.addEffect(new GainAbilitySourceEffect(DefenderAbility.getInstance(), Duration.Custom), source); game.addEffect(new GainAbilitySourceEffect(DefenderAbility.getInstance(), Duration.Custom), source);
break; break;
} }
game.addEffect(new SetPowerToughnessSourceEffect(power, toughness, Duration.Custom, SubLayer.SetPT_7b), source); permanent.getPower().modifyBaseValue(power);
permanent.getToughness().modifyBaseValue(toughness);
// game.addEffect(new SetPowerToughnessSourceEffect(power, toughness, Duration.Custom, SubLayer.SetPT_7b), source);
} }
return false; return false;

View file

@ -31,11 +31,8 @@ import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
import mage.abilities.effects.common.continuous.SetPowerSourceEffect;
import mage.abilities.effects.common.continuous.SetToughnessSourceEffect;
import mage.abilities.keyword.DefenderAbility; import mage.abilities.keyword.DefenderAbility;
import mage.abilities.keyword.HasteAbility; import mage.abilities.keyword.HasteAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
@ -95,14 +92,14 @@ class MoltenSentryEffect extends OneShotEffect {
if (controller != null && permanent != null) { if (controller != null && permanent != null) {
if (controller.flipCoin(game)) { if (controller.flipCoin(game)) {
game.informPlayers("Heads: " + permanent.getLogName() + " enters the battlefield as a 5/2 creature with haste"); game.informPlayers("Heads: " + permanent.getLogName() + " enters the battlefield as a 5/2 creature with haste");
game.addEffect(new SetPowerSourceEffect(new StaticValue(5), Duration.WhileOnBattlefield), source); permanent.getPower().modifyBaseValue(5);
game.addEffect(new SetToughnessSourceEffect(new StaticValue(2), Duration.WhileOnBattlefield), source); permanent.getToughness().modifyBaseValue(2);
game.addEffect(new GainAbilitySourceEffect(HasteAbility.getInstance(), Duration.WhileOnBattlefield), source); game.addEffect(new GainAbilitySourceEffect(HasteAbility.getInstance(), Duration.WhileOnBattlefield), source);
return true; return true;
} else { } else {
game.informPlayers("Tails: " + permanent.getLogName() + " enters the battlefield as a 2/5 creature with defender"); game.informPlayers("Tails: " + permanent.getLogName() + " enters the battlefield as a 2/5 creature with defender");
game.addEffect(new SetPowerSourceEffect(new StaticValue(2), Duration.WhileOnBattlefield), source); permanent.getPower().modifyBaseValue(2);
game.addEffect(new SetToughnessSourceEffect(new StaticValue(5), Duration.WhileOnBattlefield), source); permanent.getToughness().modifyBaseValue(5);
game.addEffect(new GainAbilitySourceEffect(DefenderAbility.getInstance(), Duration.WhileOnBattlefield), source); game.addEffect(new GainAbilitySourceEffect(DefenderAbility.getInstance(), Duration.WhileOnBattlefield), source);
return true; return true;
} }

View file

@ -80,8 +80,8 @@ class SlimeMoldingEffect extends OneShotEffect {
int count = source.getManaCostsToPay().getX(); int count = source.getManaCostsToPay().getX();
OozeToken oozeToken = new OozeToken(); OozeToken oozeToken = new OozeToken();
oozeToken.getPower().initValue(count); oozeToken.getPower().modifyBaseValue(count);
oozeToken.getToughness().initValue(count); oozeToken.getToughness().modifyBaseValue(count);
oozeToken.putOntoBattlefield(1, game, source.getSourceId(), source.getControllerId()); oozeToken.putOntoBattlefield(1, game, source.getSourceId(), source.getControllerId());
return true; return true;
} }

View file

@ -83,8 +83,8 @@ class DevastatingSummonsEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
ElementalToken token = new ElementalToken(); ElementalToken token = new ElementalToken();
token.getPower().initValue(new GetXValue().calculate(game, source, this)); token.getPower().modifyBaseValue(new GetXValue().calculate(game, source, this));
token.getToughness().initValue(new GetXValue().calculate(game, source, this)); token.getToughness().modifyBaseValue(new GetXValue().calculate(game, source, this));
token.putOntoBattlefield(2, game, source.getSourceId(), source.getControllerId()); token.putOntoBattlefield(2, game, source.getSourceId(), source.getControllerId());

View file

@ -80,8 +80,8 @@ class GelatinousGenesisEffect extends OneShotEffect {
int count = source.getManaCostsToPay().getX(); int count = source.getManaCostsToPay().getX();
OozeToken oozeToken = new OozeToken(); OozeToken oozeToken = new OozeToken();
oozeToken.getPower().initValue(count); oozeToken.getPower().modifyBaseValue(count);
oozeToken.getToughness().initValue(count); oozeToken.getToughness().modifyBaseValue(count);
oozeToken.putOntoBattlefield(count, game, source.getSourceId(), source.getControllerId()); oozeToken.putOntoBattlefield(count, game, source.getSourceId(), source.getControllerId());
return true; return true;
} }

View file

@ -72,15 +72,15 @@ class QuicksilverGargantuanApplyToPermanent extends ApplyToPermanent {
@Override @Override
public Boolean apply(Game game, Permanent permanent) { public Boolean apply(Game game, Permanent permanent) {
permanent.getPower().initValue(7); permanent.getPower().modifyBaseValue(7);
permanent.getToughness().initValue(7); permanent.getToughness().modifyBaseValue(7);
return true; return true;
} }
@Override @Override
public Boolean apply(Game game, MageObject mageObject) { public Boolean apply(Game game, MageObject mageObject) {
mageObject.getPower().initValue(7); mageObject.getPower().modifyBaseValue(7);
mageObject.getToughness().initValue(7); mageObject.getToughness().modifyBaseValue(7);
return true; return true;
} }

View file

@ -123,15 +123,18 @@ class LeechBonderEffect extends OneShotEffect {
possibleChoices.add(counterName); possibleChoices.add(counterName);
} }
choice.setChoices(possibleChoices); choice.setChoices(possibleChoices);
if (controller.choose(Outcome.AIDontUseIt, choice, game)) { if (controller.choose(outcome, choice, game)) {
String chosen = choice.getChoice(); String chosen = choice.getChoice();
if (fromPermanent.getCounters().containsKey(chosen)) { if (fromPermanent.getCounters().containsKey(chosen)) {
Counter counter = new Counter(chosen, 1); CounterType counterType = CounterType.findByName(chosen);
if (counterType != null) {
Counter counter = counterType.createInstance();
fromPermanent.removeCounters(counter, game); fromPermanent.removeCounters(counter, game);
toPermanent.addCounters(counter, game); toPermanent.addCounters(counter, game);
return true; return true;
} }
} }
}
return false; return false;
} }
} }

View file

@ -0,0 +1,111 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.tempest;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.SacrificeSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ExileTargetEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.filter.common.FilterCreatureCard;
import mage.game.ExileZone;
import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetControlledCreaturePermanent;
/**
*
* @author Plopman
*/
public class ColdStorage extends CardImpl {
public ColdStorage(UUID ownerId) {
super(ownerId, 270, "Cold Storage", Rarity.RARE, new CardType[]{CardType.ARTIFACT}, "{4}");
this.expansionSetCode = "TMP";
// {3}: Exile target creature you control.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ExileTargetEffect(this.getId(), this.getIdName()), new ManaCostsImpl("{3}"));
ability.addTarget(new TargetControlledCreaturePermanent());
this.addAbility(ability);
// Sacrifice Cold Storage: Return each creature card exiled with Cold Storage to the battlefield under your control.
ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ReturnFromExileEffect(this.getId()), new SacrificeSourceCost());
this.addAbility(ability);
}
public ColdStorage(final ColdStorage card) {
super(card);
}
@Override
public ColdStorage copy() {
return new ColdStorage(this);
}
}
class ReturnFromExileEffect extends OneShotEffect {
private UUID exileId;
public ReturnFromExileEffect(UUID exileId) {
super(Outcome.PutCardInPlay);
this.exileId = exileId;
this.setText("Return each creature card exiled with {this} to the battlefield under your control");
}
public ReturnFromExileEffect(final ReturnFromExileEffect effect) {
super(effect);
this.exileId = effect.exileId;
}
@Override
public ReturnFromExileEffect copy() {
return new ReturnFromExileEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
ExileZone exile = game.getExile().getExileZone(exileId);
Player controller = game.getPlayer(source.getControllerId());
if (controller != null && exile != null) {
controller.moveCards(exile.getCards(new FilterCreatureCard(), game), Zone.BATTLEFIELD, source, game, false, false, true, null);
return true;
}
return false;
}
}

View file

@ -0,0 +1,66 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.tempest;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.BecomesBlockedByCreatureTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.PutOnLibraryTargetEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Rarity;
/**
*
* @author Plopman
*/
public class ElvenWarhounds extends CardImpl {
public ElvenWarhounds(UUID ownerId) {
super(ownerId, 119, "Elven Warhounds", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{3}{G}");
this.expansionSetCode = "TMP";
this.subtype.add("Hound");
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// Whenever Elven Warhounds becomes blocked by a creature, put that creature on top of its owner's library.
Effect effect = new PutOnLibraryTargetEffect(true);
effect.setText("put that creature on top of its owner's library");
this.addAbility(new BecomesBlockedByCreatureTriggeredAbility(effect, false));
}
public ElvenWarhounds(final ElvenWarhounds card) {
super(card);
}
@Override
public ElvenWarhounds copy() {
return new ElvenWarhounds(this);
}
}

View file

@ -0,0 +1,158 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.tempest;
import java.util.UUID;
import mage.abilities.Abilities;
import mage.abilities.AbilitiesImpl;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.Cost;
import mage.abilities.costs.common.SacrificeTargetCost;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.abilities.effects.common.continuous.SourceEffect;
import mage.abilities.keyword.ForestwalkAbility;
import mage.abilities.keyword.IslandwalkAbility;
import mage.abilities.keyword.MountainwalkAbility;
import mage.abilities.keyword.PlainswalkAbility;
import mage.abilities.keyword.SwampwalkAbility;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Layer;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.SubLayer;
import mage.constants.Zone;
import mage.filter.common.FilterControlledLandPermanent;
import mage.filter.predicate.mageobject.SupertypePredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.common.TargetControlledPermanent;
import mage.target.common.TargetCreaturePermanent;
/**
*
* @author Plopman
*/
public class Excavator extends CardImpl {
private static final FilterControlledLandPermanent filter = new FilterControlledLandPermanent("basic land");
static
{
filter.add(new SupertypePredicate("Basic"));
}
public Excavator(UUID ownerId) {
super(ownerId, 277, "Excavator", Rarity.UNCOMMON, new CardType[]{CardType.ARTIFACT}, "{2}");
this.expansionSetCode = "TMP";
// {tap}, Sacrifice a basic land: Target creature gains landwalk of each of the land types of the sacrificed land until end of turn.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ExcavatorEffect(), new TapSourceCost());
ability.addCost(new SacrificeTargetCost(new TargetControlledPermanent(filter)));
ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability);
}
public Excavator(final Excavator card) {
super(card);
}
@Override
public Excavator copy() {
return new Excavator(this);
}
}
class ExcavatorEffect extends ContinuousEffectImpl implements SourceEffect {
private Abilities<Ability> abilities = new AbilitiesImpl();;
public ExcavatorEffect() {
super(Duration.EndOfTurn, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility);
setText("Target creature gains landwalk of each of the land types of the sacrificed land until end of turn");
}
public ExcavatorEffect(final ExcavatorEffect effect) {
super(effect);
this.abilities = abilities.copy();
}
@Override
public ExcavatorEffect copy() {
return new ExcavatorEffect(this);
}
@Override
public void init(Ability source, Game game) {
super.init(source, game);
for(Cost cost : source.getCosts()) {
if(cost instanceof SacrificeTargetCost) {
SacrificeTargetCost sacrificeCost = (SacrificeTargetCost) cost;
for(Permanent permanent : sacrificeCost.getPermanents()) {
if(permanent.hasSubtype("Forest"))
{
abilities.add(new ForestwalkAbility());
}
if(permanent.hasSubtype("Plains"))
{
abilities.add(new PlainswalkAbility());
}
if(permanent.hasSubtype("Island"))
{
abilities.add(new IslandwalkAbility());
}
if(permanent.hasSubtype("Mountain"))
{
abilities.add(new MountainwalkAbility());
}
if(permanent.hasSubtype("Swamp"))
{
abilities.add(new SwampwalkAbility());
}
}
}
}
}
@Override
public boolean apply(Game game, Ability source) {
for (UUID permanentId : targetPointer.getTargets(game, source)) {
Permanent permanent = game.getPermanentOrLKIBattlefield(permanentId);
if (permanent != null) {
for(Ability ability : abilities)
{
permanent.addAbility(ability, source.getSourceId(), game, false);
}
}
}
return true;
}
}

View file

@ -0,0 +1,141 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.tempest;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetCard;
import mage.target.common.TargetOpponent;
/**
* 10/4/2004 : If there is only one card in your graveyard, it is exiled by the first part of the effect and you do not get to put any cards into your hand since the second part fails.
* 10/15/2006: It does not target the cards, but it targets the opponent. If you can't target an opponent, you can't activate this ability.
*
* @author Plopman
*/
public class PhyrexianGrimoire extends CardImpl {
public PhyrexianGrimoire(UUID ownerId) {
super(ownerId, 291, "Phyrexian Grimoire", Rarity.RARE, new CardType[]{CardType.ARTIFACT}, "{3}");
this.expansionSetCode = "TMP";
// {4}, {tap}: Target opponent chooses one of the top two cards of your graveyard. Exile that card and put the other one into your hand.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new PhyrexianGrimoireEffect(), new ManaCostsImpl("{4}"));
ability.addCost(new TapSourceCost());
ability.addTarget(new TargetOpponent());
this.addAbility(ability);
}
public PhyrexianGrimoire(final PhyrexianGrimoire card) {
super(card);
}
@Override
public PhyrexianGrimoire copy() {
return new PhyrexianGrimoire(this);
}
}
class PhyrexianGrimoireEffect extends OneShotEffect {
public PhyrexianGrimoireEffect() {
super(Outcome.ReturnToHand);
this.staticText = "Target opponent chooses one of the top two cards of your graveyard. Exile that card and put the other one into your hand";
}
public PhyrexianGrimoireEffect(final PhyrexianGrimoireEffect effect) {
super(effect);
}
@Override
public PhyrexianGrimoireEffect copy() {
return new PhyrexianGrimoireEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Player opponent = game.getPlayer(source.getFirstTarget());
if (controller != null && opponent != null) {
if(controller.getGraveyard().size() > 0)
{
Cards cards = new CardsImpl();
UUID card1 = null;
UUID card2 = null;
for (UUID cardId : controller.getGraveyard()) {
card2 = card1;
card1 = cardId;
}
if(card1 != null){
cards.add(card1);
}
if(card2 != null){
cards.add(card2);
}
TargetCard target = new TargetCard(Zone.GRAVEYARD, new FilterCard());
target.setRequired(true);
if(opponent.choose(Outcome.Exile, cards, target, game))
{
Card card = game.getCard(target.getFirstTarget());
cards.remove(target.getFirstTarget());
if (card != null) {
controller.moveCards(card, Zone.EXILED, source, game);
}
if(!cards.isEmpty())
{
card = game.getCard(cards.iterator().next());
if (card != null) {
controller.moveCards(card, Zone.HAND, source, game);
}
}
}
}
return true;
}
return false;
}
}

View file

@ -0,0 +1,114 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.tempest;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.InvertCondition;
import mage.abilities.condition.common.SourceTappedCondition;
import mage.abilities.decorator.ConditionalContinuousEffect;
import mage.abilities.effects.common.combat.BlocksIfAbleSourceEffect;
import mage.abilities.effects.common.continuous.BoostAllEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.filter.common.FilterAttackingCreature;
import mage.game.Game;
import mage.game.combat.CombatGroup;
import mage.game.permanent.Permanent;
/**
*
* @author Plopman
*/
public class Watchdog extends CardImpl {
public Watchdog(UUID ownerId) {
super(ownerId, 304, "Watchdog", Rarity.UNCOMMON, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{3}");
this.expansionSetCode = "TMP";
this.subtype.add("Hound");
this.power = new MageInt(1);
this.toughness = new MageInt(2);
// Watchdog blocks each turn if able.
this.getAbilities().add(new SimpleStaticAbility(Zone.BATTLEFIELD, new BlocksIfAbleSourceEffect(Duration.WhileOnBattlefield)));
// As long as Watchdog is untapped, all creatures attacking you get -1/-0.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(
new BoostAllEffect(-1, 0, Duration.WhileOnBattlefield, new WatchdogFilter(), false), new InvertCondition(new SourceTappedCondition()),"As long as {this} is untapped, all creatures attacking you get -1/-0")));
}
public Watchdog(final Watchdog card) {
super(card);
}
@Override
public Watchdog copy() {
return new Watchdog(this);
}
}
class WatchdogFilter extends FilterAttackingCreature {
public WatchdogFilter() {
super("creatures attacking you");
}
public WatchdogFilter(final WatchdogFilter filter) {
super(filter);
}
@Override
public WatchdogFilter copy() {
return new WatchdogFilter(this);
}
@Override
public boolean match(Permanent permanent, UUID sourceId, UUID playerId, Game game) {
if(!super.match(permanent, sourceId, playerId, game)) {
return false;
}
for(CombatGroup group : game.getCombat().getGroups()) {
for(UUID attacker : group.getAttackers()) {
if(attacker.equals(permanent.getId())) {
UUID defenderId = group.getDefenderId();
if(defenderId.equals(playerId)) {
return true;
}
}
}
}
return false;
}
}

View file

@ -80,8 +80,8 @@ class WurmcallingEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
int count = source.getManaCostsToPay().getX(); int count = source.getManaCostsToPay().getX();
WurmToken token = new WurmToken(); WurmToken token = new WurmToken();
token.getPower().initValue(count); token.getPower().modifyBaseValue(count);
token.getToughness().initValue(count); token.getToughness().modifyBaseValue(count);
token.putOntoBattlefield(1, game, source.getSourceId(), source.getControllerId()); token.putOntoBattlefield(1, game, source.getSourceId(), source.getControllerId());
return true; return true;
} }

View file

@ -84,7 +84,7 @@ class LurkingEvilCost extends CostImpl {
@Override @Override
public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) { public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) {
Player controller = game.getPlayer(controllerId); Player controller = game.getPlayer(controllerId);
return controller != null && !(controller.getLife() > 0 && !controller.canPayLifeCost()); return controller != null && (controller.getLife() < 1 || controller.canPayLifeCost());
} }
@Override @Override

View file

@ -129,8 +129,8 @@ class PhyrexianProcessorCreateTokenEffect extends OneShotEffect {
if(object != null && object instanceof Integer) { if(object != null && object instanceof Integer) {
int lifePaid = (int) object; int lifePaid = (int) object;
MinionToken token = new MinionToken(); MinionToken token = new MinionToken();
token.getPower().initValue(lifePaid); token.getPower().modifyBaseValue(lifePaid);
token.getToughness().initValue(lifePaid); token.getToughness().modifyBaseValue(lifePaid);
token.putOntoBattlefield(1, game, source.getSourceId(), source.getControllerId()); token.putOntoBattlefield(1, game, source.getSourceId(), source.getControllerId());
return true; return true;
} }

View file

@ -0,0 +1,48 @@
package org.mage.test.cards.abilities.equipped;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import mage.game.permanent.Permanent;
import org.junit.Assert;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author escplan9 (Derek Monturo - dmontur1 at gmail dot com)
*/
public class KusariGamaTest extends CardTestPlayerBase {
// reported bug: trigger occurs but no damage is dealt
@Test
public void testTriggeredAbilityDealsDamage() {
// Kusari-Gama - Artifact Equipment - Equip {3}
// Equipped creature has "2: This creature gets +1/+0 until end of turn."
// Whenever equipped creature deals damage to a blocking creature, Kusari-Gama deals that much damage to each other creature defending player controls.
addCard(Zone.BATTLEFIELD, playerA, "Kusari-Gama");
addCard(Zone.BATTLEFIELD, playerA, "Plains", 3);
addCard(Zone.BATTLEFIELD, playerA, "Sylvan Advocate"); // 2/3 vigilance {1}{G}
addCard(Zone.BATTLEFIELD, playerB, "Wall of Omens"); // 0/4 {1}{W}
addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion", 2); // 2/2 {1}{W}
addCard(Zone.BATTLEFIELD, playerB, "Hill Giant"); // 3/3 {3}{R}
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Equip {3}", "Sylvan Advocate");
attack(1, playerA, "Sylvan Advocate");
block(1, playerB, "Wall of Omens", "Sylvan Advocate");
setStopAt(1, PhaseStep.END_COMBAT);
execute();
assertPermanentCount(playerA, "Kusari-Gama", 1);
assertPermanentCount(playerB, "Wall of Omens", 1);
assertPermanentCount(playerB, "Hill Giant", 1);
Permanent wallPerm = getPermanent("Wall of Omens", playerB);
Permanent giantPerm = getPermanent("Hill Giant", playerB);
Assert.assertEquals("Wall of Omens should have 2 damage dealt to it", 2, wallPerm.getDamage());
Assert.assertEquals("Hill Giant should have 2 damage dealt to it", 2, giantPerm.getDamage());
assertGraveyardCount(playerB, "Silvercoat Lion", 2);
}
}

View file

@ -389,7 +389,7 @@ public class BestowTest extends CardTestPlayerBase {
// Bestow 4W (If you cast this card for its bestow cost, it's an Aura spell with enchant creature. It becomes a creature again if it's not attached to a creature.) // Bestow 4W (If you cast this card for its bestow cost, it's an Aura spell with enchant creature. It becomes a creature again if it's not attached to a creature.)
// Sightless Brawler can't attack alone. // Sightless Brawler can't attack alone.
// Enchanted creature gets +3/+2 and can't attack alone. // Enchanted creature gets +3/+2 and can't attack alone.
addCard(Zone.BATTLEFIELD, playerA, "Sightless Brawler"); addCard(Zone.BATTLEFIELD, playerA, "Sightless Brawler"); // 3/2
addCard(Zone.BATTLEFIELD, playerA, "Elite Vanguard"); // {W} 2/1 creature addCard(Zone.BATTLEFIELD, playerA, "Elite Vanguard"); // {W} 2/1 creature
attack(1, playerA, "Sightless Brawler"); attack(1, playerA, "Sightless Brawler");

View file

@ -116,4 +116,44 @@ public class EscalateTest extends CardTestPlayerBase {
assertLife(playerB, 17); assertLife(playerB, 17);
} }
@Test
public void testSpellQuellerInteraction_ThreeCMC_ThreeModes() {
// {1}{W}{U} Flash Flying 2/3 Spirit
// When Spell Queller enters the battlefield, exile target spell with converted mana cost 4 or less.
// When Spell Queller leaves the battlefield, the exiled card's owner may cast that card without paying its mana cost.
addCard(Zone.HAND, playerB, "Spell Queller");
addCard(Zone.BATTLEFIELD, playerB, "Wall of Omens"); // {1}{W} 0/4
addCard(Zone.BATTLEFIELD, playerB, "Island", 2);
addCard(Zone.BATTLEFIELD, playerB, "Plains", 1);
// Escalate {1} (Pay this cost for each mode chosen beyond the first.)
// Choose one or more
// * Target player discards all the cards in his or her hand, then draws that many cards.
// * Collective Defiance deals 4 damage to target creature.
// * Collective Defiance deals 3 damage to target opponent.
addCard(Zone.HAND, playerA, "Collective Defiance"); // {1}{R}{R} sorcery
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 5);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Collective Defiance", "mode=2Wall of Omens");
setModeChoice(playerA, "1"); // opponent discards hand and draws that many
setModeChoice(playerA, "2"); // deal 4 dmg to target creature (Wall of Omens)
setModeChoice(playerA, "3"); // deal 3 dmg to opponent
addTarget(playerA, playerB); // mode 1
addTarget(playerA, playerB); // mode 3
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Spell Queller");
addTarget(playerB, "Collective Defiance");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertPermanentCount(playerB, "Spell Queller", 1);
assertHandCount(playerA, "Collective Defiance", 0);
assertExileCount("Collective Defiance", 1);
assertGraveyardCount(playerA, "Collective Defiance", 0);
assertPermanentCount(playerB, "Wall of Omens", 1);
assertLife(playerA, 20);
assertLife(playerB, 20);
}
} }

View file

@ -264,4 +264,45 @@ public class FlashbackTest extends CardTestPlayerBase {
assertGraveyardCount(playerA, "Snapcaster Mage", 1); assertGraveyardCount(playerA, "Snapcaster Mage", 1);
} }
/**
* Fracturing Gust is bugged. In a match against Affinity, it worked
* properly when cast from hand. When I cast it from graveyard c/o
* Snapcaster Mage flashback, it destroyed my opponent's Darksteel Citadels,
* which it did not do when cast from my hand.
*/
@Test
public void testSnapcasterMageWithIcefallRegent() {
addCard(Zone.BATTLEFIELD, playerA, "Island", 2);
addCard(Zone.HAND, playerA, "Snapcaster Mage", 1);
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2);
// Destroy target creature. It can't be regenerated.
addCard(Zone.GRAVEYARD, playerA, "Terminate");
addCard(Zone.BATTLEFIELD, playerA, "Berserkers' Onslaught", 1);
addCard(Zone.BATTLEFIELD, playerB, "Icefall Regent", 1);
// When Snapcaster Mage enters the battlefield, target instant or sorcery card in your graveyard gains flashback until end of turn. The flashback cost is equal to its mana cost.
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Snapcaster Mage");
setChoice(playerA, "Terminate");
activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Flashback"); // Flashback Terminate
addTarget(playerA, "Icefall Regent");
setStopAt(1, PhaseStep.END_TURN);
execute();
assertPermanentCount(playerA, "Snapcaster Mage", 1);
assertGraveyardCount(playerB, "Icefall Regent", 1);
assertExileCount("Terminate", 1);
assertTappedCount("Mountain", true, 2);
assertTappedCount("Island", true, 2);
assertTappedCount("Swamp", true, 2);
}
} }

View file

@ -225,6 +225,8 @@ public class MorphTest extends CardTestPlayerBase {
*/ */
@Test @Test
public void testPineWalkerWithUnboostEffect() { public void testPineWalkerWithUnboostEffect() {
// Morph {4}{G}
// Whenever Pine Walker or another creature you control is turned face up, untap that creature.
addCard(Zone.HAND, playerA, "Pine Walker"); addCard(Zone.HAND, playerA, "Pine Walker");
addCard(Zone.BATTLEFIELD, playerA, "Forest", 8); addCard(Zone.BATTLEFIELD, playerA, "Forest", 8);
@ -643,12 +645,13 @@ public class MorphTest extends CardTestPlayerBase {
} }
/** /**
* Reflector Mage bouncing a creature that can be played as a morph should not prevent the card * Reflector Mage bouncing a creature that can be played as a morph should
* from being replayed as a morph. Morph creatures are nameless. * not prevent the card from being replayed as a morph. Morph creatures are
* nameless.
* *
* Reported bug: * Reported bug: Face-up morph creatures that are bounced by Reflector Mage
* Face-up morph creatures that are bounced by Reflector Mage should be able to be replayed as morphs * should be able to be replayed as morphs without the "until the next turn"
* without the "until the next turn" restriction." * restriction."
*/ */
@Test @Test
public void testReflectorMageBouncesFaceupCreatureReplayAsMorph() { public void testReflectorMageBouncesFaceupCreatureReplayAsMorph() {
@ -684,12 +687,13 @@ public class MorphTest extends CardTestPlayerBase {
} }
/** /**
* Reflector Mage bouncing a creature that can be played as a morph should not prevent the card * Reflector Mage bouncing a creature that can be played as a morph should
* from being replayed as a morph. Morph creatures are nameless. * not prevent the card from being replayed as a morph. Morph creatures are
* nameless.
* *
* Reported bug: * Reported bug: Face-up morph creatures that are bounced by Reflector Mage
* Face-up morph creatures that are bounced by Reflector Mage should be able to be replayed as morphs * should be able to be replayed as morphs without the "until the next turn"
* without the "until the next turn" restriction." * restriction."
* *
* Testing bouncing a face-down creature played next turn face-up. * Testing bouncing a face-down creature played next turn face-up.
*/ */

View file

@ -25,7 +25,6 @@
* authors and should not be interpreted as representing official policies, either expressed * authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com. * or implied, of BetaSteward_at_googlemail.com.
*/ */
package org.mage.test.cards.abilities.keywords; package org.mage.test.cards.abilities.keywords;
import mage.constants.PhaseStep; import mage.constants.PhaseStep;
@ -38,15 +37,13 @@ import org.mage.test.serverside.base.CardTestPlayerBase;
* *
* @author LevelX2 * @author LevelX2
*/ */
public class ProliferateTest extends CardTestPlayerBase { public class ProliferateTest extends CardTestPlayerBase {
/** /**
* Volt Charge {2}{R} * Volt Charge {2}{R} Instant Volt Charge deals 3 damage to target creature
* Instant * or player. Proliferate. (You choose any number of permanents and/or
* Volt Charge deals 3 damage to target creature or player. * players with counters on them, then give each another counter of a kind
* Proliferate. (You choose any number of permanents and/or players with counters * already there.)
* on them, then give each another counter of a kind already there.)
*/ */
@Test @Test
public void testCastFromHandMovedToExile() { public void testCastFromHandMovedToExile() {
@ -55,11 +52,9 @@ public class ProliferateTest extends CardTestPlayerBase{
addCard(Zone.HAND, playerA, "Volt Charge"); addCard(Zone.HAND, playerA, "Volt Charge");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Volt Charge", playerB); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Volt Charge", playerB);
addTarget(playerA, "Chandra, Pyromaster"); addTarget(playerA, "Chandra, Pyromaster");
setStopAt(1, PhaseStep.BEGIN_COMBAT); setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute(); execute();
@ -71,11 +66,14 @@ public class ProliferateTest extends CardTestPlayerBase{
} }
/** /**
* Counters aren't cancelling each other out. Reproducible with any creature (graft and bloodthirst in my case) * Counters aren't cancelling each other out. Reproducible with any creature
* with a single +1/+1 counter on it, with a single -1/-1 placed on it (Grim Affliction, Instill Infection, etc). * (graft and bloodthirst in my case) with a single +1/+1 counter on it,
* The counters should cancel each other out, leaving neither on the creature, which they don't (though visually * with a single -1/-1 placed on it (Grim Affliction, Instill Infection,
* there aren't any counters sitting on the card). Triggering proliferate at any point now (Thrumming Bird, * etc). The counters should cancel each other out, leaving neither on the
* Steady Progress, etc) will give you the option to add another of either counter, where you shouldn't have any as an option. * creature, which they don't (though visually there aren't any counters
* sitting on the card). Triggering proliferate at any point now (Thrumming
* Bird, Steady Progress, etc) will give you the option to add another of
* either counter, where you shouldn't have any as an option.
*/ */
@Test @Test
public void testValidTargets() { public void testValidTargets() {
@ -104,13 +102,13 @@ public class ProliferateTest extends CardTestPlayerBase{
setStopAt(2, PhaseStep.BEGIN_COMBAT); setStopAt(2, PhaseStep.BEGIN_COMBAT);
execute(); execute();
assertGraveyardCount(playerA, "Battlegrowth", 1); assertGraveyardCount(playerA, "Battlegrowth", 1);
assertGraveyardCount(playerA, "Steady Progress", 1); assertGraveyardCount(playerA, "Steady Progress", 1);
assertGraveyardCount(playerB, "Grim Affliction", 1); assertGraveyardCount(playerB, "Grim Affliction", 1);
assertCounterCount("Silvercoat Lion", CounterType.P1P1, 0); // no valid target because no counter assertCounterCount("Silvercoat Lion", CounterType.P1P1, 0); // no valid target because no counter
assertCounterCount("Sporeback Troll", CounterType.P1P1, 3); // 2 + 1 from proliferate assertCounterCount("Sporeback Troll", CounterType.P1P1, 3); // 2 + 1 from proliferate
assertPowerToughness(playerB, "Sporeback Troll", 3, 3);
} }
} }

View file

@ -76,6 +76,7 @@ public class UndyingTest extends CardTestPlayerBase {
execute(); execute();
assertPermanentCount(playerA, "Elite Vanguard", 1); assertPermanentCount(playerA, "Elite Vanguard", 1);
assertCounterCount(playerA, "Elite Vanguard", CounterType.P1P1, 1);
assertPowerToughness(playerA, "Elite Vanguard", 3, 2); assertPowerToughness(playerA, "Elite Vanguard", 3, 2);
} }
@ -112,6 +113,7 @@ public class UndyingTest extends CardTestPlayerBase {
assertGraveyardCount(playerA, "Lightning Bolt", 1); assertGraveyardCount(playerA, "Lightning Bolt", 1);
assertPermanentCount(playerB, "Strangleroot Geist", 0); assertPermanentCount(playerB, "Strangleroot Geist", 0);
assertPermanentCount(playerA, "Strangleroot Geist", 1); assertPermanentCount(playerA, "Strangleroot Geist", 1);
assertCounterCount(playerA, "Strangleroot Geist", CounterType.P1P1, 1);
assertPowerToughness(playerA, "Strangleroot Geist", 3, 2); assertPowerToughness(playerA, "Strangleroot Geist", 3, 2);
} }
@ -211,6 +213,7 @@ public class UndyingTest extends CardTestPlayerBase {
assertPermanentCount(playerA, "Silvercoat Lion", 1); assertPermanentCount(playerA, "Silvercoat Lion", 1);
assertPermanentCount(playerA, "Mikaeus, the Unhallowed", 1); assertPermanentCount(playerA, "Mikaeus, the Unhallowed", 1);
assertCounterCount(playerA, "Silvercoat Lion", CounterType.P1P1, 1);
assertPowerToughness(playerA, "Silvercoat Lion", 4, 4); assertPowerToughness(playerA, "Silvercoat Lion", 4, 4);
} }
@ -272,4 +275,45 @@ public class UndyingTest extends CardTestPlayerBase {
} }
/**
* I stole my opponents Vorapede using Simic Manipulator and shortly after
* someone played Wrath of God. Instead of returning to my opponent's board,
* Vorapede came back under my control. The rules text for Undying states
* that it should return under its owner's control, not its controller's.
*/
@Test
public void testUndyingCreatureReturnsUnderOwnersControl() {
// Creature Insect
// Vigilance, trample
// Undying (When this creature dies, if it had no +1/+1 counters on it, return it to the battlefield under its owner's control with a +1/+1 counter on it.)
addCard(Zone.BATTLEFIELD, playerB, "Vorapede"); // {2}{G}{G}{G} 5/4
addCard(Zone.HAND, playerB, "Doom Blade"); // {1}{B} destroy target non-black creature
addCard(Zone.BATTLEFIELD, playerB, "Swamp", 2);
// {2}{R} sorcery - Gain control of target creature until end of turn. Untap that creature. It gains haste until end of turn.
addCard(Zone.HAND, playerA, "Act of Treason");
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
// playerA takes control of Vorapede from playerB
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Act of Treason", "Vorapede");
attack(1, playerA, "Vorapede");
// playerB kills Vorapede under the control of playerA now
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Doom Blade", "Vorapede");
setStopAt(1, PhaseStep.END_TURN);
execute();
assertLife(playerA, 20);
assertLife(playerB, 15);
assertGraveyardCount(playerA, "Act of Treason", 1);
assertGraveyardCount(playerB, "Doom Blade", 1);
// Vorapede should return under control of playerA, not playerB
assertPermanentCount(playerB, "Vorapede", 1);
assertPermanentCount(playerA, "Vorapede", 0);
assertCounterCount(playerB, "Vorapede", CounterType.P1P1, 1);
assertPowerToughness(playerB, "Vorapede", 6, 5);
}
} }

View file

@ -106,4 +106,37 @@ public class MovingCounterTest extends CardTestPlayerBase {
assertPowerToughness(playerA, "Ruin Processor", 3, 4); assertPowerToughness(playerA, "Ruin Processor", 3, 4);
} }
/**
* The card Leech Bonder (or the token mechanic) doesn't seem to work quite
* as intended. If moving a -1/-1 counter from the Leech Bonder onto an
* enemy creature with 1/1 the creature stays as a 1/1 with the token being
* displayed on it. Going by the rules the creature should have 0/0 and thus
* be put into the graveyard.
*/
@Test
public void testLeechBonder() {
addCard(Zone.BATTLEFIELD, playerA, "Island", 3);
// Leech Bonder enters the battlefield with two -1/-1 counters on it.
// {U}, {untap}: Move a counter from target creature onto another target creature.
addCard(Zone.HAND, playerA, "Leech Bonder", 1);// Creature 3/3 - {2}{U}
addCard(Zone.BATTLEFIELD, playerB, "Ley Druid", 1); // 1/1
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Leech Bonder");
attack(3, playerA, "Leech Bonder");
activateAbility(3, PhaseStep.POSTCOMBAT_MAIN, playerA, "{U},", "Leech Bonder");
addTarget(playerA, "Ley Druid");
setStopAt(3, PhaseStep.END_TURN);
execute();
assertLife(playerB, 19);
assertGraveyardCount(playerB, "Ley Druid", 1);
assertPowerToughness(playerA, "Leech Bonder", 2, 2);
}
} }

View file

@ -31,6 +31,8 @@ import mage.abilities.keyword.IndestructibleAbility;
import mage.constants.PhaseStep; import mage.constants.PhaseStep;
import mage.constants.Zone; import mage.constants.Zone;
import mage.counters.CounterType; import mage.counters.CounterType;
import mage.game.permanent.Permanent;
import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase; import org.mage.test.serverside.base.CardTestPlayerBase;
@ -115,4 +117,47 @@ public class GideonTest extends CardTestPlayerBase {
} }
/**
* When you use Gideon, Battle-Forged (flipped version of Kytheon from Magic
* Origins) and use his 0 ability to turn him into a creature and equip the
* Stitcher's Graft from EMN, he should have to be sacced at the end of
* turn.
*/
@Test
public void testGideonBattleForgedSacrifice() {
addCard(Zone.BATTLEFIELD, playerB, "Mountain", 2);
// At end of combat, if Kytheon, Hero of Akros and at least two other creatures attacked this combat, exile Kytheon,
// then return him to the battlefield transformed under his owner's control.
// {2}{W}: Kytheon gains indestructible until end of turn.
// Gideon, Battle-Forged
// +2: Up to one target creature an opponent controls attacks Gideon, Battle-Forged during its controller's next turn if able.
// +1: Until your next turn, target creature gains indestructible. Untap that creature.
// +0: Until end of turn, Gideon, Battle-Forged becomes a 4/4 Human Soldier creature with indestructible that's still a planeswalker. Prevent all damage that would be dealt to him this turn.
addCard(Zone.BATTLEFIELD, playerB, "Kytheon, Hero of Akros");
addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion");
addCard(Zone.BATTLEFIELD, playerB, "Pillarfield Ox");
// Equipped creature gets +3/+3.
// Whenever equipped creature attacks, it doesn't untap during its controller's next untap step.
// Whenever Stitcher's Graft becomes unattached from a permanent, sacrifice that permanent.
// Equip {2}
addCard(Zone.BATTLEFIELD, playerB, "Stitcher's Graft", 1);
attack(2, playerB, "Kytheon, Hero of Akros");
attack(2, playerB, "Silvercoat Lion");
attack(2, playerB, "Pillarfield Ox");
activateAbility(4, PhaseStep.PRECOMBAT_MAIN, playerB, "+0: Until ");
activateAbility(4, PhaseStep.PRECOMBAT_MAIN, playerB, "Equip {2}", "Gideon, Battle-Forged");
attack(4, playerB, "Gideon, Battle-Forged"); // 7 damage
setStopAt(5, PhaseStep.PRECOMBAT_MAIN);
execute();
assertPermanentCount(playerB, "Silvercoat Lion", 1);
assertLife(playerA, 7);
Permanent equipment = getPermanent("Stitcher's Graft", playerB);
Assert.assertTrue("Stitcher's Graft may no longer be equipped", equipment.getAttachedTo() == null);
assertPermanentCount(playerB, "Gideon, Battle-Forged", 0);
assertGraveyardCount(playerB, "Kytheon, Hero of Akros", 1);
}
} }

View file

@ -0,0 +1,68 @@
package org.mage.test.cards.replacement;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Ignore;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author escplan9 (Derek Monturo - dmontur1 at gmail dot com)
*/
public class ClergyOfTheHolyNimbusTest extends CardTestPlayerBase {
@Test
public void testBasicRegeneration() {
// If Clergy of the Holy Nimbus would be destroyed, regenerate it.
// {1}: Clergy of the Holy Nimbus can't be regenerated this turn. Only any opponent may activate this ability.
addCard(Zone.BATTLEFIELD, playerB, "Clergy of the Holy Nimbus"); // {W} 1/1
addCard(Zone.HAND, playerA, "Doom Blade"); // {1}{B} destroy target non-black creature
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Doom Blade", "Clergy of the Holy Nimbus");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertGraveyardCount(playerA, "Doom Blade", 1);
assertPermanentCount(playerB, "Clergy of the Holy Nimbus", 1);
}
@Test
public void testCannotBeRegeneratedSpell() {
// If Clergy of the Holy Nimbus would be destroyed, regenerate it.
// {1}: Clergy of the Holy Nimbus can't be regenerated this turn. Only any opponent may activate this ability.
addCard(Zone.BATTLEFIELD, playerB, "Clergy of the Holy Nimbus"); // {W} 1/1
addCard(Zone.HAND, playerA, "Wrath of God"); // {2}{W}{W} destroy all creatures, they cannot be regenerated
addCard(Zone.BATTLEFIELD, playerA, "Plains", 4);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Wrath of God");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertGraveyardCount(playerA, "Wrath of God", 1);
assertGraveyardCount(playerB, "Clergy of the Holy Nimbus", 1);
}
// in game testing works correctly - not sure if the ability is being activated or not here.
@Ignore
@Test
public void testOpponentPaysOneToNotAllowRegeneration() {
// If Clergy of the Holy Nimbus would be destroyed, regenerate it.
// {1}: Clergy of the Holy Nimbus can't be regenerated this turn. Only any opponent may activate this ability.
addCard(Zone.BATTLEFIELD, playerB, "Clergy of the Holy Nimbus"); // {W} 1/1
addCard(Zone.HAND, playerA, "Doom Blade"); // {1}{B} destroy target non-black creature
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3);
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{1}:");
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Doom Blade", "Clergy of the Holy Nimbus");
setStopAt(1, PhaseStep.END_TURN);
execute();
assertGraveyardCount(playerA, "Doom Blade", 1);
assertGraveyardCount(playerB, "Clergy of the Holy Nimbus", 1);
}
}

View file

@ -13,7 +13,11 @@ public class AltarOfTheLostTest extends CardTestPlayerBase {
@Test @Test
public void testCard() { public void testCard() {
// Altar of the Lost enters the battlefield tapped.
// {tap}: Add two mana in any combination of colors to your mana pool. Spend this mana only to cast spells with flashback from a graveyard.
addCard(Zone.BATTLEFIELD, playerA, "Altar of the Lost"); addCard(Zone.BATTLEFIELD, playerA, "Altar of the Lost");
// Put two 1/1 white Spirit creature tokens with flying onto the battlefield.
// Flashback {1}{B}
addCard(Zone.GRAVEYARD, playerA, "Lingering Souls"); addCard(Zone.GRAVEYARD, playerA, "Lingering Souls");
setChoice(playerA, "Black"); setChoice(playerA, "Black");

View file

@ -381,7 +381,9 @@ public class TestPlayer implements Player {
@Override @Override
public boolean priority(Game game) { public boolean priority(Game game) {
int numberOfActions = actions.size(); int numberOfActions = actions.size();
for (PlayerAction action : actions) { List<PlayerAction> tempActions = new ArrayList<>();
tempActions.addAll(actions);
for (PlayerAction action : tempActions) {
if (action.getTurnNum() == game.getTurnNum() && action.getStep() == game.getStep().getType()) { if (action.getTurnNum() == game.getTurnNum() && action.getStep() == game.getStep().getType()) {
if (action.getAction().startsWith("activate:")) { if (action.getAction().startsWith("activate:")) {
@ -478,7 +480,7 @@ public class TestPlayer implements Player {
int turns = Integer.parseUnsignedInt(groups[1].substring(6)); int turns = Integer.parseUnsignedInt(groups[1].substring(6));
game.rollbackTurns(turns); game.rollbackTurns(turns);
actions.remove(action); actions.remove(action);
break; return true;
} }
} }
} }

View file

@ -25,7 +25,6 @@
* authors and should not be interpreted as representing official policies, either expressed * authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com. * or implied, of BetaSteward_at_googlemail.com.
*/ */
package mage; package mage;
import java.io.Serializable; import java.io.Serializable;
@ -49,15 +48,28 @@ public class MageInt implements Serializable, Copyable<MageInt> {
}; };
protected int baseValue; protected int baseValue;
protected int baseValueModified;
protected int boostedValue;
protected String cardValue = ""; protected String cardValue = "";
public MageInt(int value) { public MageInt(int value) {
this.baseValue = value; this.baseValue = value;
this.baseValueModified = baseValue;
this.boostedValue = baseValue;
this.cardValue = Integer.toString(value); this.cardValue = Integer.toString(value);
} }
public MageInt(int baseValue, String cardValue) { public MageInt(int baseValue, String cardValue) {
this.baseValue = baseValue; this.baseValue = baseValue;
this.baseValueModified = baseValue;
this.boostedValue = baseValue;
this.cardValue = cardValue;
}
public MageInt(int baseValue, int baseValueModified, int boostedValue, String cardValue) {
this.baseValue = baseValue;
this.baseValueModified = baseValueModified;
this.boostedValue = boostedValue;
this.cardValue = cardValue; this.cardValue = cardValue;
} }
@ -66,24 +78,37 @@ public class MageInt implements Serializable, Copyable<MageInt> {
if (this == EmptyMageInt) { if (this == EmptyMageInt) {
return this; return this;
} }
return new MageInt(baseValue, cardValue); return new MageInt(baseValue, baseValueModified, boostedValue, cardValue);
} }
public int getValue() { public int getBaseValue() {
return baseValue; return baseValue;
} }
public void initValue(int value) { public int getBaseValueModified() {
this.baseValue = value; return baseValueModified;
}
public int getValue() {
return boostedValue;
}
public void modifyBaseValue(int value) {
this.baseValueModified = value;
this.boostedValue = value;
this.cardValue = Integer.toString(value); this.cardValue = Integer.toString(value);
} }
public void setValue(int value) { public void setValue(int value) {
this.baseValue = value; this.boostedValue = value;
} }
public void boostValue(int amount) { public void boostValue(int amount) {
this.baseValue += amount; this.boostedValue += amount;
}
public void resetToBaseValue() {
this.boostedValue = this.baseValueModified;
} }
@Override @Override

View file

@ -176,8 +176,7 @@ public class SpellAbility extends ActivatedAbilityImpl {
return cardName; return cardName;
} }
public int getConvertedManaCost() { public int getConvertedXManaCost() {
int cmc = 0;
int xMultiplier = 0; int xMultiplier = 0;
for (String symbolString : getManaCosts().getSymbols()) { for (String symbolString : getManaCosts().getSymbols()) {
int index = symbolString.indexOf("{X}"); int index = symbolString.indexOf("{X}");
@ -187,12 +186,7 @@ public class SpellAbility extends ActivatedAbilityImpl {
index = symbolString.indexOf("{X}"); index = symbolString.indexOf("{X}");
} }
} }
if (getSpellAbilityType().equals(SpellAbilityType.BASE_ALTERNATE)) { return getManaCostsToPay().getX() * xMultiplier;
cmc += getManaCostsToPay().getX() * xMultiplier;
} else {
cmc += getManaCosts().convertedManaCost() + getManaCostsToPay().getX() * xMultiplier;
}
return cmc;
} }
} }

View file

@ -0,0 +1,53 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package mage.abilities.effects.common.combat;
import mage.abilities.Ability;
import mage.abilities.effects.RestrictionEffect;
import mage.constants.AttachmentType;
import mage.constants.Duration;
import mage.game.Game;
import mage.game.permanent.Permanent;
/**
*
* @author LevelX2
*/
public class CantAttackAloneAttachedEffect extends RestrictionEffect {
public CantAttackAloneAttachedEffect(AttachmentType attachmentType) {
super(Duration.WhileOnBattlefield);
if (attachmentType.equals(AttachmentType.AURA)) {
this.staticText = "Enchanted creature can't attack alone";
} else {
this.staticText = "Equipped creature can't attack alone";
}
}
public CantAttackAloneAttachedEffect(final CantAttackAloneAttachedEffect effect) {
super(effect);
}
@Override
public CantAttackAloneAttachedEffect copy() {
return new CantAttackAloneAttachedEffect(this);
}
@Override
public boolean canAttackCheckAfter(int numberOfAttackers, Ability source, Game game) {
return numberOfAttackers > 1;
}
@Override
public boolean applies(Permanent permanent, Ability source, Game game) {
Permanent attachment = game.getPermanent(source.getSourceId());
if (attachment != null && attachment.getAttachedTo() != null
&& permanent.getId().equals(attachment.getAttachedTo())) {
return true;
}
return false;
}
}

View file

@ -15,20 +15,20 @@ import mage.game.permanent.Permanent;
* *
* @author LevelX2 * @author LevelX2
*/ */
public class CantAttackAloneEffect extends RestrictionEffect { public class CantAttackAloneSourceEffect extends RestrictionEffect {
public CantAttackAloneEffect() { public CantAttackAloneSourceEffect() {
super(Duration.WhileOnBattlefield); super(Duration.WhileOnBattlefield);
staticText = "{this} can't attack alone"; staticText = "{this} can't attack alone";
} }
public CantAttackAloneEffect(final CantAttackAloneEffect effect) { public CantAttackAloneSourceEffect(final CantAttackAloneSourceEffect effect) {
super(effect); super(effect);
} }
@Override @Override
public CantAttackAloneEffect copy() { public CantAttackAloneSourceEffect copy() {
return new CantAttackAloneEffect(this); return new CantAttackAloneSourceEffect(this);
} }
@Override @Override

View file

@ -47,13 +47,12 @@ import mage.game.Game;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
/** /**
* This effect lets the card be a 2/2 face-down creature, with no text, * This effect lets the card be a 2/2 face-down creature, with no text, no name,
* no name, no subtypes, and no mana cost, if it's face down on the battlefield. * no subtypes, and no mana cost, if it's face down on the battlefield. And it
* And it adds the a TurnFaceUpAbility ability. * adds the a TurnFaceUpAbility ability.
* *
* @author LevelX2 * @author LevelX2
*/ */
public class BecomesFaceDownCreatureEffect extends ContinuousEffectImpl implements SourceEffect { public class BecomesFaceDownCreatureEffect extends ContinuousEffectImpl implements SourceEffect {
public enum FaceDownType { public enum FaceDownType {
@ -97,7 +96,6 @@ public class BecomesFaceDownCreatureEffect extends ContinuousEffectImpl implemen
this.faceDownType = faceDownType; this.faceDownType = faceDownType;
} }
public BecomesFaceDownCreatureEffect(final BecomesFaceDownCreatureEffect effect) { public BecomesFaceDownCreatureEffect(final BecomesFaceDownCreatureEffect effect) {
super(effect); super(effect);
this.zoneChangeCounter = effect.zoneChangeCounter; this.zoneChangeCounter = effect.zoneChangeCounter;
@ -184,13 +182,11 @@ public class BecomesFaceDownCreatureEffect extends ContinuousEffectImpl implemen
if (ability.getWorksFaceDown()) { if (ability.getWorksFaceDown()) {
ability.setRuleVisible(false); ability.setRuleVisible(false);
continue; continue;
} else { } else if (!ability.getRuleVisible() && !ability.getEffects().isEmpty()) {
if (!ability.getRuleVisible() && !ability.getEffects().isEmpty()) {
if (ability.getEffects().get(0) instanceof BecomesFaceDownCreatureEffect) { if (ability.getEffects().get(0) instanceof BecomesFaceDownCreatureEffect) {
continue; continue;
} }
} }
}
abilitiesToRemove.add(ability); abilitiesToRemove.add(ability);
} }
permanent.getAbilities().removeAll(abilitiesToRemove); permanent.getAbilities().removeAll(abilitiesToRemove);
@ -200,15 +196,13 @@ public class BecomesFaceDownCreatureEffect extends ContinuousEffectImpl implemen
break; break;
case PTChangingEffects_7: case PTChangingEffects_7:
if (sublayer == SubLayer.SetPT_7b) { if (sublayer == SubLayer.SetPT_7b) {
permanent.getPower().setValue(2); // permanent.getPower().setValue(2);
permanent.getToughness().setValue(2); // permanent.getToughness().setValue(2);
} }
} }
} else { } else if (duration.equals(Duration.Custom) && foundPermanent == true) {
if (duration.equals(Duration.Custom) && foundPermanent == true) {
discard(); discard();
} }
}
return true; return true;
} }

View file

@ -115,7 +115,7 @@ public class BoostTargetEffect extends ContinuousEffectImpl {
if (staticText != null && !staticText.isEmpty()) { if (staticText != null && !staticText.isEmpty()) {
return staticText; return staticText;
} }
if (mode == null || mode.getTargets().size() == 0) { if (mode == null || mode.getTargets().isEmpty()) {
return "no target"; return "no target";
} }
Target target = mode.getTargets().get(0); Target target = mode.getTargets().get(0);

View file

@ -28,7 +28,7 @@
package mage.abilities.keyword; package mage.abilities.keyword;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.combat.CantAttackAloneEffect; import mage.abilities.effects.common.combat.CantAttackAloneSourceEffect;
import mage.constants.Zone; import mage.constants.Zone;
/** /**
@ -37,7 +37,7 @@ import mage.constants.Zone;
public class CantAttackAloneAbility extends SimpleStaticAbility { public class CantAttackAloneAbility extends SimpleStaticAbility {
public CantAttackAloneAbility() { public CantAttackAloneAbility() {
super(Zone.BATTLEFIELD, new CantAttackAloneEffect()); super(Zone.BATTLEFIELD, new CantAttackAloneSourceEffect());
} }
private CantAttackAloneAbility(CantAttackAloneAbility ability) { private CantAttackAloneAbility(CantAttackAloneAbility ability) {

View file

@ -75,6 +75,7 @@ public class FlashbackAbility extends SpellAbility {
this.timing = timingRule; this.timing = timingRule;
this.usesStack = false; this.usesStack = false;
this.spellAbilityType = SpellAbilityType.BASE_ALTERNATE; this.spellAbilityType = SpellAbilityType.BASE_ALTERNATE;
setCostModificationActive(false);
} }
public FlashbackAbility(final FlashbackAbility ability) { public FlashbackAbility(final FlashbackAbility ability) {
@ -195,7 +196,9 @@ class FlashbackEffect extends OneShotEffect {
spellAbility.clear(); spellAbility.clear();
// set the payed flashback costs to the spell ability so abilities like Converge or calculation of {X} values work // set the payed flashback costs to the spell ability so abilities like Converge or calculation of {X} values work
spellAbility.getManaCostsToPay().clear(); spellAbility.getManaCostsToPay().clear();
spellAbility.getManaCostsToPay().addAll(source.getManaCostsToPay()); spellAbility.getManaCostsToPay().addAll(source.getManaCosts());
spellAbility.getManaCosts().clear();
spellAbility.getManaCosts().addAll(source.getManaCosts());
// needed to get e.g. paid costs from Conflagrate // needed to get e.g. paid costs from Conflagrate
for (Cost cost : source.getCosts()) { for (Cost cost : source.getCosts()) {
if (!(cost instanceof VariableCost)) { if (!(cost instanceof VariableCost)) {
@ -205,7 +208,6 @@ class FlashbackEffect extends OneShotEffect {
if (!game.isSimulation()) { if (!game.isSimulation()) {
game.informPlayers(controller.getLogName() + " flashbacks " + card.getLogName()); game.informPlayers(controller.getLogName() + " flashbacks " + card.getLogName());
} }
spellAbility.setCostModificationActive(false); // prevents to apply cost modification twice for flashbacked spells
if (controller.cast(spellAbility, game, false)) { if (controller.cast(spellAbility, game, false)) {
ContinuousEffect effect = new FlashbackReplacementEffect(); ContinuousEffect effect = new FlashbackReplacementEffect();
effect.setTargetPointer(new FixedTarget(source.getSourceId(), game.getState().getZoneChangeCounter(source.getSourceId()))); effect.setTargetPointer(new FixedTarget(source.getSourceId(), game.getState().getZoneChangeCounter(source.getSourceId())));

View file

@ -295,8 +295,8 @@ public class MorphAbility extends StaticAbility implements AlternativeSourceCost
} }
public static void setPermanentToFaceDownCreature(MageObject mageObject) { public static void setPermanentToFaceDownCreature(MageObject mageObject) {
mageObject.getPower().initValue(2); mageObject.getPower().modifyBaseValue(2);
mageObject.getToughness().initValue(2); mageObject.getToughness().modifyBaseValue(2);
mageObject.getAbilities().clear(); mageObject.getAbilities().clear();
mageObject.getColor(null).setColor(new ObjectColor()); mageObject.getColor(null).setColor(new ObjectColor());
mageObject.setName(""); mageObject.setName("");

View file

@ -166,4 +166,13 @@ public enum CounterType {
return new Counter(name, amount); return new Counter(name, amount);
} }
} }
public static CounterType findByName(String name) {
for (CounterType counterType : values()) {
if (counterType.getName().equals(name)) {
return counterType;
}
}
return null;
}
} }

View file

@ -61,6 +61,8 @@ public class PermanentCard extends PermanentImpl {
} }
private void init(Card card, Game game) { private void init(Card card, Game game) {
power = card.getPower().copy();
toughness = card.getToughness().copy();
copyFromCard(card); copyFromCard(card);
// if temporary added abilities to the spell/card exist, you need to add it to the permanent derived from that card // if temporary added abilities to the spell/card exist, you need to add it to the permanent derived from that card
Abilities<Ability> otherAbilities = game.getState().getAllOtherAbilities(card.getId()); Abilities<Ability> otherAbilities = game.getState().getAllOtherAbilities(card.getId());
@ -94,6 +96,8 @@ public class PermanentCard extends PermanentImpl {
// when the permanent is reset, copy all original values from the card // when the permanent is reset, copy all original values from the card
// must copy card each reset so that the original values don't get modified // must copy card each reset so that the original values don't get modified
copyFromCard(card); copyFromCard(card);
power.resetToBaseValue();
toughness.resetToBaseValue();
super.reset(game); super.reset(game);
} }
@ -115,8 +119,6 @@ public class PermanentCard extends PermanentImpl {
this.cardType.addAll(card.getCardType()); this.cardType.addAll(card.getCardType());
this.color = card.getColor(null).copy(); this.color = card.getColor(null).copy();
this.manaCost = card.getManaCost().copy(); this.manaCost = card.getManaCost().copy();
this.power = card.getPower().copy();
this.toughness = card.getToughness().copy();
if (card instanceof PermanentCard) { if (card instanceof PermanentCard) {
this.maxLevelCounters = ((PermanentCard) card).maxLevelCounters; this.maxLevelCounters = ((PermanentCard) card).maxLevelCounters;
} }
@ -232,6 +234,8 @@ public class PermanentCard extends PermanentImpl {
@Override @Override
public boolean turnFaceUp(Game game, UUID playerId) { public boolean turnFaceUp(Game game, UUID playerId) {
if (super.turnFaceUp(game, playerId)) { if (super.turnFaceUp(game, playerId)) {
power.modifyBaseValue(power.getBaseValue());
toughness.modifyBaseValue(toughness.getBaseValue());
setManifested(false); setManifested(false);
setMorphed(false); setMorphed(false);
return true; return true;
@ -241,7 +245,7 @@ public class PermanentCard extends PermanentImpl {
@Override @Override
public void adjustTargets(Ability ability, Game game) { public void adjustTargets(Ability ability, Game game) {
if (this.isTransformed()) { if (this.isTransformed() && card.getSecondCardFace() != null) {
card.getSecondCardFace().adjustTargets(ability, game); card.getSecondCardFace().adjustTargets(ability, game);
} else { } else {
card.adjustTargets(ability, game); card.adjustTargets(ability, game);
@ -250,7 +254,7 @@ public class PermanentCard extends PermanentImpl {
@Override @Override
public void adjustCosts(Ability ability, Game game) { public void adjustCosts(Ability ability, Game game) {
if (this.isTransformed()) { if (this.isTransformed() && card.getSecondCardFace() != null) {
card.getSecondCardFace().adjustCosts(ability, game); card.getSecondCardFace().adjustCosts(ability, game);
} else { } else {
card.adjustCosts(ability, game); card.adjustCosts(ability, game);

View file

@ -82,8 +82,8 @@ public class PermanentToken extends PermanentImpl {
} }
this.cardType = token.getCardType(); this.cardType = token.getCardType();
this.color = token.getColor(game).copy(); this.color = token.getColor(game).copy();
this.power.initValue(token.getPower().getValue()); this.power.modifyBaseValue(token.getPower().getBaseValueModified());
this.toughness.initValue(token.getToughness().getValue()); this.toughness.modifyBaseValue(token.getToughness().getBaseValueModified());
this.supertype = token.getSupertype(); this.supertype = token.getSupertype();
this.subtype = token.getSubtype(); this.subtype = token.getSubtype();
} }

View file

@ -84,8 +84,8 @@ public class Token extends MageObjectImpl {
public Token(String name, String description, int power, int toughness) { public Token(String name, String description, int power, int toughness) {
this(name, description); this(name, description);
this.power.setValue(power); this.power.modifyBaseValue(power);
this.toughness.setValue(toughness); this.toughness.modifyBaseValue(toughness);
} }
public Token(String name, String description, ObjectColor color, List<String> subtype, int power, int toughness, Abilities<Ability> abilities) { public Token(String name, String description, ObjectColor color, List<String> subtype, int power, int toughness, Abilities<Ability> abilities) {
@ -93,8 +93,8 @@ public class Token extends MageObjectImpl {
this.cardType.add(CardType.CREATURE); this.cardType.add(CardType.CREATURE);
this.color = color.copy(); this.color = color.copy();
this.subtype = subtype; this.subtype = subtype;
this.power.setValue(power); this.power.modifyBaseValue(power);
this.toughness.setValue(toughness); this.toughness.modifyBaseValue(toughness);
if (abilities != null) { if (abilities != null) {
this.abilities = abilities.copy(); this.abilities = abilities.copy();
} }
@ -264,19 +264,15 @@ public class Token extends MageObjectImpl {
if (availableImageSetCodes.size() > 0) { if (availableImageSetCodes.size() > 0) {
if (availableImageSetCodes.contains(code)) { if (availableImageSetCodes.contains(code)) {
setOriginalExpansionSetCode(code); setOriginalExpansionSetCode(code);
} else { } else // we should not set random set if appropriate set is already used
// we should not set random set if appropriate set is already used
if (getOriginalExpansionSetCode() == null || getOriginalExpansionSetCode().isEmpty() if (getOriginalExpansionSetCode() == null || getOriginalExpansionSetCode().isEmpty()
|| !availableImageSetCodes.contains(getOriginalExpansionSetCode())) { || !availableImageSetCodes.contains(getOriginalExpansionSetCode())) {
setOriginalExpansionSetCode(availableImageSetCodes.get(new Random().nextInt(availableImageSetCodes.size()))); setOriginalExpansionSetCode(availableImageSetCodes.get(new Random().nextInt(availableImageSetCodes.size())));
} }
} } else if (getOriginalExpansionSetCode() == null || getOriginalExpansionSetCode().isEmpty()) {
} else {
if (getOriginalExpansionSetCode() == null || getOriginalExpansionSetCode().isEmpty()) {
setOriginalExpansionSetCode(code); setOriginalExpansionSetCode(code);
} }
} }
}
public boolean updateExpansionSetCode(String setCode) { public boolean updateExpansionSetCode(String setCode) {
if (setCode == null || setCode.isEmpty()) { if (setCode == null || setCode.isEmpty()) {

View file

@ -503,11 +503,9 @@ public class Spell extends StackObjImpl implements Card {
return 0; return 0;
} }
for (SpellAbility spellAbility : spellAbilities) { for (SpellAbility spellAbility : spellAbilities) {
cmc += spellAbility.getConvertedManaCost(); cmc += spellAbility.getConvertedXManaCost();
} }
if (this.getSpellAbility().getSpellAbilityType().equals(SpellAbilityType.BASE_ALTERNATE)) {
cmc += getCard().getManaCost().convertedManaCost(); cmc += getCard().getManaCost().convertedManaCost();
}
return cmc; return cmc;
} }

View file

@ -1134,7 +1134,7 @@ public abstract class PlayerImpl implements Player, Serializable {
} }
} else { } else {
int bookmark = game.bookmarkState(); int bookmark = game.bookmarkState();
if (ability.activate(game, false)) { if (ability.activate(game, ability instanceof FlashbackAbility)) {
ability.resolve(game); ability.resolve(game);
game.removeBookmark(bookmark); game.removeBookmark(bookmark);
resetStoredBookmark(game); resetStoredBookmark(game);

View file

@ -108,9 +108,9 @@ public class CopyTokenFunction implements Function<Token, Card> {
ability.setSourceId(target.getId()); ability.setSourceId(target.getId());
target.addAbility(ability); target.addAbility(ability);
} }
// Needed to do it this way because only the cardValue does not include the increased value from cards like "Intangible Virtue" will be copied.
target.getPower().initValue(Integer.parseInt(sourceObj.getPower().toString())); target.getPower().modifyBaseValue(sourceObj.getPower().getBaseValueModified());
target.getToughness().initValue(Integer.parseInt(sourceObj.getToughness().toString())); target.getToughness().modifyBaseValue(sourceObj.getToughness().getBaseValueModified());
return target; return target;
} }