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);
if (player != null && !player.hasQuit()) {
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

@ -64,7 +64,7 @@ public class KusariGama extends CardImpl {
this.subtype.add("Equipment");
// Equipped creature has "{2}: This creature gets +1/+0 until end of turn."
Ability gainedAbility = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostSourceEffect(1,0, Duration.EndOfTurn), new GenericManaCost(2));
Ability gainedAbility = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostSourceEffect(1, 0, Duration.EndOfTurn), new GenericManaCost(2));
Effect effect = new GainAbilityAttachedEffect(gainedAbility, AttachmentType.EQUIPMENT);
effect.setText("Equipped creature has \"{2}: This creature gets +1/+0 until end of turn.\"");
Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, effect);
@ -144,22 +144,20 @@ class KusariGamaDamageEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Integer damage = (Integer) this.getValue("damageAmount");
if (damage != null && damage.intValue() > 0) {
if (damage != null && damage > 0) {
UUID damagedCreatureId = (UUID) this.getValue("damagedCreatureId");
Permanent creature = game.getPermanent(damagedCreatureId);
if (creature == null) {
creature = (Permanent) game.getLastKnownInformation(damagedCreatureId, Zone.BATTLEFIELD);
}
if (creature != null) {
for (UUID blockerId : game.getCombat().getBlockers()) {
if (!blockerId.equals(damagedCreatureId)) {
Permanent blockingCreature = game.getPermanent(blockerId);
if (blockingCreature != null && blockingCreature.getControllerId().equals(creature.getControllerId())) {
blockingCreature.damage(damage, source.getSourceId(), game, false, true);
}
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(new FilterCreaturePermanent(), creature.getControllerId(), game)) {
if (!permanent.getId().equals(damagedCreatureId)) {
permanent.damage(damage, source.getSourceId(), game, false, true);
}
}
}
return true;
}
return false;
}

View file

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

View file

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

View file

@ -113,8 +113,8 @@ class WireflyToken extends Token {
WireflyToken() {
super("Wirefly", "2/2 colorless Insect artifact creature token named Wirefly");
this.setOriginalExpansionSetCode("DST");
this.getPower().initValue(2);
this.getToughness().initValue(2);
this.getPower().modifyBaseValue(2);
this.getToughness().modifyBaseValue(2);
this.getSubtype().add("Insect");
this.getCardType().add(CardType.ARTIFACT);
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
public boolean checkTrigger(GameEvent event, Game game) {
if (event.getSourceId().equals(this.getSourceId())) {
return true;
}
return false;
return event.getSourceId().equals(this.getSourceId());
}
@Override
@ -141,7 +138,11 @@ class IdentityThiefEffect extends OneShotEffect {
Player controller = game.getPlayer(source.getControllerId());
Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId());
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)) {
// Copy exiled permanent
game.addEffect(copyEffect, source);

View file

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

View file

@ -27,8 +27,12 @@
*/
package mage.sets.eldritchmoon;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbility;
import mage.abilities.common.BeginningOfYourEndStepTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
@ -36,7 +40,6 @@ import mage.abilities.condition.CompoundCondition;
import mage.abilities.condition.Condition;
import mage.abilities.condition.InvertCondition;
import mage.abilities.condition.common.AttachedCondition;
import mage.abilities.condition.common.WatcherCondition;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.decorator.ConditionalTriggeredAbility;
import mage.abilities.effects.common.SacrificeEquippedEffect;
@ -50,6 +53,7 @@ import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.watchers.Watcher;
/**
*
* @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.
TriggeredAbility ability = new BeginningOfYourEndStepTriggeredAbility(new SacrificeEquippedEffect(), false);
Condition condition = new CompoundCondition(
new AttachedCondition(),
new InvertCondition(new WatcherCondition(CombatDamageToCreatureByEquippedWatcher.BASIC_KEY, WatcherScope.CARD)));
AttachedCondition.getInstance(),
new InvertCondition(new EquippedDealtCombatDamageToCreatureCondition()));
String triggeredAbilityText = "At the beginning of your end step, if equipped creature " +
"didn't deal combat damage to a creature this turn, sacrifice it.";
ConditionalTriggeredAbility sacrificeTriggeredAbility = new ConditionalTriggeredAbility(ability, condition, triggeredAbilityText);
this.addAbility(sacrificeTriggeredAbility, new CombatDamageToCreatureByEquippedWatcher());
this.addAbility(sacrificeTriggeredAbility, new CombatDamageToCreatureWatcher());
// Equip {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";
public CombatDamageToCreatureByEquippedWatcher() {
super(BASIC_KEY, WatcherScope.CARD);
@Override
public boolean apply(Game game, Ability source) {
Permanent equipment = game.getPermanent(source.getSourceId());
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);
dealtCombatDamageToCreature = new HashSet<>(watcher.dealtCombatDamageToCreature);
}
@Override
public CombatDamageToCreatureByEquippedWatcher copy() {
return new CombatDamageToCreatureByEquippedWatcher(this);
public CombatDamageToCreatureWatcher copy() {
return new CombatDamageToCreatureWatcher(this);
}
@Override
public void watch(GameEvent event, Game game) {
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()) {
condition = true;
}
}
if (((DamagedCreatureEvent) event).isCombatDamage()) {
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.costs.common.TapSourceCost;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.continuous.SetPowerToughnessSourceEffect;
import mage.abilities.keyword.DefenderAbility;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.SubLayer;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.permanent.Permanent;
@ -108,7 +105,9 @@ class TreeOfPerditionEffect extends OneShotEffect {
return false;
}
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;
}
}

View file

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

View file

@ -31,7 +31,7 @@ import java.util.UUID;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.common.UnattachedTriggeredAbility;
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.keyword.EquipAbility;
import mage.cards.CardImpl;
@ -55,7 +55,7 @@ public class GraftedWargear extends CardImpl {
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(3, 2)));
// 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}
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.effects.ReplacementEffectImpl;
import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
import mage.abilities.effects.common.continuous.SetPowerToughnessSourceEffect;
import mage.abilities.keyword.DefenderAbility;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
@ -43,7 +42,6 @@ import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.SubLayer;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.EntersTheBattlefieldEvent;
@ -152,7 +150,9 @@ class PrimalPlasmaReplacementEffect extends ReplacementEffectImpl {
game.addEffect(new GainAbilitySourceEffect(DefenderAbility.getInstance(), Duration.Custom), source);
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;

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

@ -1,117 +1,117 @@
/*
* 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.gatecrash;
import java.util.List;
import java.util.UUID;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.CardImpl;
import mage.filter.common.FilterCreaturePermanent;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.game.permanent.token.Token;
import mage.players.Player;
/**
*
* @author LevelX2
*/
public class MimingSlime extends CardImpl {
public MimingSlime(UUID ownerId) {
super(ownerId, 126, "Miming Slime", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{2}{G}");
this.expansionSetCode = "GTC";
// Put an X/X green Ooze creature token onto the battlefield, where X is the greatest power among creatures you control.
this.getSpellAbility().addEffect(new MimingSlimeEffect());
}
public MimingSlime(final MimingSlime card) {
super(card);
}
@Override
public MimingSlime copy() {
return new MimingSlime(this);
}
}
class MimingSlimeEffect extends OneShotEffect {
public MimingSlimeEffect() {
super(Outcome.PutCreatureInPlay);
staticText = "Put an X/X green Ooze creature token onto the battlefield, where X is the greatest power among creatures you control";
}
public MimingSlimeEffect(final MimingSlimeEffect effect) {
super(effect);
}
@Override
public MimingSlimeEffect copy() {
return new MimingSlimeEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player != null) {
List<Permanent> creatures = game.getBattlefield().getAllActivePermanents(new FilterCreaturePermanent(), player.getId(), game);
int amount = 0;
for (Permanent creature : creatures) {
int power = creature.getPower().getValue();
if (amount < power) {
amount = power;
}
}
OozeToken oozeToken = new OozeToken();
oozeToken.getPower().initValue(amount);
oozeToken.getToughness().initValue(amount);
oozeToken.putOntoBattlefield(1, game, source.getSourceId(), source.getControllerId());
return true;
}
return false;
}
}
class OozeToken extends Token {
public OozeToken() {
super("Ooze", "X/X green Ooze creature token");
cardType.add(CardType.CREATURE);
subtype.add("Ooze");
color.setGreen(true);
power = new MageInt(0);
toughness = new MageInt(0);
setOriginalExpansionSetCode("RTR");
}
}
/*
* 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.gatecrash;
import java.util.List;
import java.util.UUID;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.CardImpl;
import mage.filter.common.FilterCreaturePermanent;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.game.permanent.token.Token;
import mage.players.Player;
/**
*
* @author LevelX2
*/
public class MimingSlime extends CardImpl {
public MimingSlime(UUID ownerId) {
super(ownerId, 126, "Miming Slime", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{2}{G}");
this.expansionSetCode = "GTC";
// Put an X/X green Ooze creature token onto the battlefield, where X is the greatest power among creatures you control.
this.getSpellAbility().addEffect(new MimingSlimeEffect());
}
public MimingSlime(final MimingSlime card) {
super(card);
}
@Override
public MimingSlime copy() {
return new MimingSlime(this);
}
}
class MimingSlimeEffect extends OneShotEffect {
public MimingSlimeEffect() {
super(Outcome.PutCreatureInPlay);
staticText = "Put an X/X green Ooze creature token onto the battlefield, where X is the greatest power among creatures you control";
}
public MimingSlimeEffect(final MimingSlimeEffect effect) {
super(effect);
}
@Override
public MimingSlimeEffect copy() {
return new MimingSlimeEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player != null) {
List<Permanent> creatures = game.getBattlefield().getAllActivePermanents(new FilterCreaturePermanent(), player.getId(), game);
int amount = 0;
for (Permanent creature : creatures) {
int power = creature.getPower().getValue();
if (amount < power) {
amount = power;
}
}
OozeToken oozeToken = new OozeToken();
oozeToken.getPower().modifyBaseValue(amount);
oozeToken.getToughness().modifyBaseValue(amount);
oozeToken.putOntoBattlefield(1, game, source.getSourceId(), source.getControllerId());
return true;
}
return false;
}
}
class OozeToken extends Token {
public OozeToken() {
super("Ooze", "X/X green Ooze creature token");
cardType.add(CardType.CREATURE);
subtype.add("Ooze");
color.setGreen(true);
power = new MageInt(0);
toughness = new MageInt(0);
setOriginalExpansionSetCode("RTR");
}
}

View file

@ -1,109 +1,109 @@
/*
* 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.gatecrash;
import java.util.UUID;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.Cost;
import mage.abilities.costs.common.RemoveVariableCountersTargetCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
import mage.cards.CardImpl;
import mage.counters.CounterType;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.game.Game;
import mage.game.permanent.token.Token;
/**
*
* @author LevelX2
*/
public class OozeFlux extends CardImpl {
public OozeFlux(UUID ownerId) {
super(ownerId, 128, "Ooze Flux", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{3}{G}");
this.expansionSetCode = "GTC";
// {1}{G}, Remove one or more +1/+1 counters from among creatures you control: Put an X/X green Ooze creature token onto the battlefield, where X is the number of +1/+1 counters removed this way.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new OozeFluxCreateTokenEffect(new OozeToken()),new ManaCostsImpl("{1}{G}"));
ability.addCost(new RemoveVariableCountersTargetCost(new FilterControlledCreaturePermanent("creatures you control"), CounterType.P1P1, "one or more", 1));
this.addAbility(ability);
}
public OozeFlux(final OozeFlux card) {
super(card);
}
@Override
public OozeFlux copy() {
return new OozeFlux(this);
}
}
class OozeFluxCreateTokenEffect extends OneShotEffect {
private final Token token;
public OozeFluxCreateTokenEffect(Token token) {
super(Outcome.PutCreatureInPlay);
this.token = token;
staticText = "Put an X/X green Ooze creature token onto the battlefield, where X is the number of +1/+1 counters removed this way";
}
public OozeFluxCreateTokenEffect(final OozeFluxCreateTokenEffect effect) {
super(effect);
this.token = effect.token.copy();
}
@Override
public OozeFluxCreateTokenEffect copy() {
return new OozeFluxCreateTokenEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
int xValue = 0;
for (Cost cost : source.getCosts()) {
if (cost instanceof RemoveVariableCountersTargetCost) {
xValue = ((RemoveVariableCountersTargetCost) cost).getAmount();
break;
}
}
Token tokenCopy = token.copy();
tokenCopy.getAbilities().newId();
tokenCopy.getPower().initValue(xValue);
tokenCopy.getToughness().initValue(xValue);
tokenCopy.putOntoBattlefield(1, game, source.getSourceId(), source.getControllerId());
return true;
}
}
/*
* 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.gatecrash;
import java.util.UUID;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.Cost;
import mage.abilities.costs.common.RemoveVariableCountersTargetCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
import mage.cards.CardImpl;
import mage.counters.CounterType;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.game.Game;
import mage.game.permanent.token.Token;
/**
*
* @author LevelX2
*/
public class OozeFlux extends CardImpl {
public OozeFlux(UUID ownerId) {
super(ownerId, 128, "Ooze Flux", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{3}{G}");
this.expansionSetCode = "GTC";
// {1}{G}, Remove one or more +1/+1 counters from among creatures you control: Put an X/X green Ooze creature token onto the battlefield, where X is the number of +1/+1 counters removed this way.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new OozeFluxCreateTokenEffect(new OozeToken()),new ManaCostsImpl("{1}{G}"));
ability.addCost(new RemoveVariableCountersTargetCost(new FilterControlledCreaturePermanent("creatures you control"), CounterType.P1P1, "one or more", 1));
this.addAbility(ability);
}
public OozeFlux(final OozeFlux card) {
super(card);
}
@Override
public OozeFlux copy() {
return new OozeFlux(this);
}
}
class OozeFluxCreateTokenEffect extends OneShotEffect {
private final Token token;
public OozeFluxCreateTokenEffect(Token token) {
super(Outcome.PutCreatureInPlay);
this.token = token;
staticText = "Put an X/X green Ooze creature token onto the battlefield, where X is the number of +1/+1 counters removed this way";
}
public OozeFluxCreateTokenEffect(final OozeFluxCreateTokenEffect effect) {
super(effect);
this.token = effect.token.copy();
}
@Override
public OozeFluxCreateTokenEffect copy() {
return new OozeFluxCreateTokenEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
int xValue = 0;
for (Cost cost : source.getCosts()) {
if (cost instanceof RemoveVariableCountersTargetCost) {
xValue = ((RemoveVariableCountersTargetCost) cost).getAmount();
break;
}
}
Token tokenCopy = token.copy();
tokenCopy.getAbilities().newId();
tokenCopy.getPower().modifyBaseValue(xValue);
tokenCopy.getToughness().modifyBaseValue(xValue);
tokenCopy.putOntoBattlefield(1, game, source.getSourceId(), source.getControllerId());
return true;
}
}

View file

@ -91,8 +91,8 @@ class SkeletonToken extends Token {
SkeletonToken() {
super("Skeleton", "1/1 black Skeleton creature token onto the battlefield. It has \"{B}: Regenerate this creature.\"");
this.setOriginalExpansionSetCode("HML");
this.getPower().initValue(1);
this.getToughness().initValue(1);
this.getPower().modifyBaseValue(1);
this.getToughness().modifyBaseValue(1);
this.color.setBlack(true);
this.getSubtype().add("Skeleton");
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) {
Permanent sourceObject = game.getPermanentOrLKIBattlefield(source.getSourceId());
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;
}

View file

@ -73,14 +73,13 @@ public class PharikaGodOfAffliction extends CardImpl {
// As long as your devotion to black and green is less than seven, Pharika isn't a creature.
Effect effect = new LoseCreatureTypeSourceEffect(new DevotionCount(ColoredManaSymbol.B, ColoredManaSymbol.G), 7);
effect.setText("As long as your devotion to black and green is less than seven, Pharika isn't a creature");
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect));
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect));
// {B}{G}: Exile target creature card from a graveyard. It's owner puts a 1/1 black and green Snake enchantment creature token with deathtouch onto the battlefield.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new PharikaExileEffect(), new ManaCostsImpl("{B}{G}"));
Target target = new TargetCardInGraveyard(new FilterCreatureCard("a creature card from a graveyard"));
ability.addTarget(target);
this.addAbility(ability);
}
public PharikaGodOfAffliction(final PharikaGodOfAffliction card) {
@ -98,7 +97,7 @@ class PharikaExileEffect extends OneShotEffect {
public PharikaExileEffect() {
super(Outcome.PutCreatureInPlay);
staticText = "Exile target creature card from a graveyard. It's owner puts a 1/1 black and green Snake enchantment creature token with deathtouch onto the battlefield";
}
}
public PharikaExileEffect(final PharikaExileEffect effect) {
super(effect);
@ -116,8 +115,8 @@ class PharikaExileEffect extends OneShotEffect {
Player tokenController = game.getPlayer(targetCard.getOwnerId());
if (tokenController != null) {
return new PharikaSnakeToken().putOntoBattlefield(1, game, source.getSourceId(), tokenController.getId());
}
}
}
}
}
return false;
}
@ -132,15 +131,13 @@ class PharikaExileEffect extends OneShotEffect {
class PharikaSnakeToken extends Token {
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");
cardType.add(CardType.ENCHANTMENT);
cardType.add(CardType.CREATURE);
subtype.add("Snake");
color.setBlack(true);
color.setGreen(true);
power.setValue(1);
toughness.setValue(1);
this.addAbility(DeathtouchAbility.getInstance());
}
}

View file

@ -32,11 +32,12 @@ import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
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.keyword.BestowAbility;
import mage.abilities.keyword.CantAttackAloneAbility;
import mage.cards.CardImpl;
import mage.constants.AttachmentType;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Rarity;
@ -65,7 +66,7 @@ public class SightlessBrawler extends CardImpl {
Effect effect = new BoostEnchantedEffect(3, 2, Duration.WhileOnBattlefield);
effect.setText("Enchanted creature gets +3/+2");
Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, effect);
effect = new CanAttackOnlyAloneEffect();
effect = new CantAttackAloneAttachedEffect(AttachmentType.AURA);
effect.setText("and can't attack alone");
ability.addEffect(effect);
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");
this.setOriginalExpansionSetCode("ORI");
this.getSupertype().add("Legendary");
this.getPower().initValue(4);
this.getToughness().initValue(4);
this.getPower().modifyBaseValue(4);
this.getToughness().modifyBaseValue(4);
this.color.setGreen(true);
this.getSubtype().add("Elemental");
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;
}
HorrorToken horrorToken = new HorrorToken();
horrorToken.getPower().initValue(count);
horrorToken.getToughness().initValue(count);
horrorToken.getPower().modifyBaseValue(count);
horrorToken.getToughness().modifyBaseValue(count);
horrorToken.putOntoBattlefield(1, game, source.getSourceId(), source.getControllerId());
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() {
super("Cat Warrior", "2/2 green Cat Warrior creature token with forestwalk");
this.setOriginalExpansionSetCode("PLC");
this.getPower().initValue(2);
this.getToughness().initValue(2);
this.getPower().modifyBaseValue(2);
this.getToughness().modifyBaseValue(2);
this.color.setGreen(true);
this.getSubtype().add("Cat");
this.getSubtype().add("Warrior");

View file

@ -33,7 +33,6 @@ import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ReplacementEffectImpl;
import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
import mage.abilities.effects.common.continuous.SetPowerToughnessSourceEffect;
import mage.abilities.keyword.DefenderAbility;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
@ -43,7 +42,6 @@ import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.SubLayer;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.EntersTheBattlefieldEvent;
@ -153,7 +151,9 @@ class PrimalPlasmaReplacementEffect extends ReplacementEffectImpl {
game.addEffect(new GainAbilitySourceEffect(DefenderAbility.getInstance(), Duration.Custom), source);
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;

View file

@ -31,11 +31,8 @@ import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.OneShotEffect;
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.HasteAbility;
import mage.cards.CardImpl;
@ -95,14 +92,14 @@ class MoltenSentryEffect extends OneShotEffect {
if (controller != null && permanent != null) {
if (controller.flipCoin(game)) {
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);
game.addEffect(new SetToughnessSourceEffect(new StaticValue(2), Duration.WhileOnBattlefield), source);
permanent.getPower().modifyBaseValue(5);
permanent.getToughness().modifyBaseValue(2);
game.addEffect(new GainAbilitySourceEffect(HasteAbility.getInstance(), Duration.WhileOnBattlefield), source);
return true;
} else {
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);
game.addEffect(new SetToughnessSourceEffect(new StaticValue(5), Duration.WhileOnBattlefield), source);
permanent.getPower().modifyBaseValue(2);
permanent.getToughness().modifyBaseValue(5);
game.addEffect(new GainAbilitySourceEffect(DefenderAbility.getInstance(), Duration.WhileOnBattlefield), source);
return true;
}

View file

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

View file

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

View file

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

View file

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

View file

@ -123,13 +123,16 @@ class LeechBonderEffect extends OneShotEffect {
possibleChoices.add(counterName);
}
choice.setChoices(possibleChoices);
if (controller.choose(Outcome.AIDontUseIt, choice, game)) {
if (controller.choose(outcome, choice, game)) {
String chosen = choice.getChoice();
if (fromPermanent.getCounters().containsKey(chosen)) {
Counter counter = new Counter(chosen, 1);
fromPermanent.removeCounters(counter, game);
toPermanent.addCounters(counter, game);
return true;
CounterType counterType = CounterType.findByName(chosen);
if (counterType != null) {
Counter counter = counterType.createInstance();
fromPermanent.removeCounters(counter, game);
toPermanent.addCounters(counter, game);
return true;
}
}
}
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) {
int count = source.getManaCostsToPay().getX();
WurmToken token = new WurmToken();
token.getPower().initValue(count);
token.getToughness().initValue(count);
token.getPower().modifyBaseValue(count);
token.getToughness().modifyBaseValue(count);
token.putOntoBattlefield(1, game, source.getSourceId(), source.getControllerId());
return true;
}

View file

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

View file

@ -129,8 +129,8 @@ class PhyrexianProcessorCreateTokenEffect extends OneShotEffect {
if(object != null && object instanceof Integer) {
int lifePaid = (int) object;
MinionToken token = new MinionToken();
token.getPower().initValue(lifePaid);
token.getToughness().initValue(lifePaid);
token.getPower().modifyBaseValue(lifePaid);
token.getToughness().modifyBaseValue(lifePaid);
token.putOntoBattlefield(1, game, source.getSourceId(), source.getControllerId());
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

@ -362,7 +362,7 @@ public class BestowTest extends CardTestPlayerBase {
Assert.assertEquals("Nighthowler has to be a creature", true, nighthowler.getCardType().contains(CardType.CREATURE));
}
@Test
public void testSightlessBrawlerCantAttackAloneEnforced() {
addCard(Zone.BATTLEFIELD, playerA, "Plains", 5);
@ -373,14 +373,14 @@ public class BestowTest extends CardTestPlayerBase {
// Enchanted creature gets +3/+2 and can't attack alone.
addCard(Zone.BATTLEFIELD, playerA, "Sightless Brawler");
attack(1, playerA, "Sightless Brawler");
setStopAt(1,PhaseStep.END_COMBAT);
attack(1, playerA, "Sightless Brawler");
setStopAt(1, PhaseStep.END_COMBAT);
execute();
assertLife(playerB, 20);
assertTapped("Sightless Brawler", false);
}
@Test
public void testSightlessBrawlerAttacksWithOthers() {
addCard(Zone.BATTLEFIELD, playerA, "Plains", 5);
@ -389,18 +389,18 @@ 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.)
// Sightless Brawler 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
attack(1, playerA, "Sightless Brawler");
attack(1, playerA, "Elite Vanguard");
setStopAt(1,PhaseStep.END_COMBAT);
setStopAt(1, PhaseStep.END_COMBAT);
execute();
assertLife(playerB, 15);
assertTapped("Sightless Brawler", true);
}
@Test
public void testSightlessBrawlerBestowedCantAttackAloneEnforced() {
addCard(Zone.BATTLEFIELD, playerA, "Plains", 5);
@ -414,15 +414,15 @@ public class BestowTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Sightless Brawler using bestow", "Elite Vanguard");
attack(1, playerA, "Elite Vanguard");
setStopAt(1,PhaseStep.END_COMBAT);
setStopAt(1, PhaseStep.END_COMBAT);
execute();
assertHandCount(playerA, "Sightless Brawler", 0);
assertLife(playerB, 20);
assertTapped("Elite Vanguard", false);
assertPowerToughness(playerA, "Elite Vanguard", 5, 3); // 2/1 + 3/2 = 5/3
}
@Test
public void testSightlessBrawlerBestowedAttacksWithOthers() {
addCard(Zone.BATTLEFIELD, playerA, "Plains", 5);
@ -438,9 +438,9 @@ public class BestowTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Sightless Brawler using bestow", "Elite Vanguard");
attack(1, playerA, "Elite Vanguard");
attack(1, playerA, "Memnite");
setStopAt(1,PhaseStep.END_COMBAT);
setStopAt(1, PhaseStep.END_COMBAT);
execute();
assertHandCount(playerA, "Sightless Brawler", 0);
assertLife(playerB, 14);
assertTapped("Elite Vanguard", true);

View file

@ -115,5 +115,45 @@ public class EscalateTest extends CardTestPlayerBase {
assertGraveyardCount(playerB, "Gaddock Teeg", 1);
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

@ -244,15 +244,15 @@ public class FlashbackTest extends CardTestPlayerBase {
assertGraveyardCount(playerA, "Silent Departure", 1);
assertGraveyardCount(playerA, "Runic Repetition", 1);
}
@Test
public void testAltarsReap() {
addCard(Zone.LIBRARY, playerA, "Island", 2);
addCard(Zone.GRAVEYARD, playerA, "Altar's Reap", 1);
addCard(Zone.BATTLEFIELD, playerA, "Underground Sea", 4);
addCard(Zone.HAND, playerA, "Snapcaster Mage", 1);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Snapcaster Mage");
setChoice(playerA, "Altar's Reap");
@ -261,7 +261,48 @@ public class FlashbackTest extends CardTestPlayerBase {
setStopAt(1, PhaseStep.END_TURN);
execute();
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
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.BATTLEFIELD, playerA, "Forest", 8);
@ -641,24 +643,25 @@ public class MorphTest extends CardTestPlayerBase {
assertPowerToughness(playerA, "Pine Walker", 5, 5);
assertTapped("Pine Walker", false);
}
/**
* Reflector Mage bouncing a creature that can be played as a morph should not prevent the card
* from being replayed as a morph. Morph creatures are nameless.
*
* Reported bug:
* Face-up morph creatures that are bounced by Reflector Mage should be able to be replayed as morphs
* without the "until the next turn" restriction."
* Reflector Mage bouncing a creature that can be played as a morph should
* not prevent the card from being replayed as a morph. Morph creatures are
* nameless.
*
* Reported bug: Face-up morph creatures that are bounced by Reflector Mage
* should be able to be replayed as morphs without the "until the next turn"
* restriction."
*/
@Test
public void testReflectorMageBouncesFaceupCreatureReplayAsMorph() {
// {1}{W}{U} When Reflector Mage enters the battlefield, return target creature an opponent controls to its owner's hand.
// {1}{W}{U} When Reflector Mage enters the battlefield, return target creature an opponent controls to its owner's hand.
// That creature's owner can't cast spells with the same name as that creature until your next turn.
addCard(Zone.HAND, playerA, "Reflector Mage"); // 2/3
addCard(Zone.BATTLEFIELD, playerA, "Plains", 2);
addCard(Zone.BATTLEFIELD, playerA, "Island", 2);
//Tap: Add {G}, {U}, or {R} to your mana pool.
// Morph 2 (You may cast this card face down as a 2/2 creature for 3. Turn it face up any time for its morph cost.)
// When Rattleclaw Mystic is turned face up, add {G}{U}{R} to your mana pool.
@ -666,36 +669,37 @@ public class MorphTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerB, "Forest");
addCard(Zone.BATTLEFIELD, playerB, "Island");
addCard(Zone.BATTLEFIELD, playerB, "Mountain");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Reflector Mage");
addTarget(playerA, "Rattleclaw Mystic");
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Rattleclaw Mystic");
setChoice(playerB, "Yes"); // cast it face down as 2/2 creature
setStopAt(2, PhaseStep.BEGIN_COMBAT);
execute();
assertPermanentCount(playerA, "Reflector Mage", 1);
assertPermanentCount(playerB, "Rattleclaw Mystic", 0);
assertPermanentCount(playerA, "Reflector Mage", 1);
assertPermanentCount(playerB, "Rattleclaw Mystic", 0);
assertHandCount(playerB, "Rattleclaw Mystic", 0); // should have been replayed
assertPermanentCount(playerB, "", 1); // Rattleclaw played as a morph
}
/**
* Reflector Mage bouncing a creature that can be played as a morph should not prevent the card
* from being replayed as a morph. Morph creatures are nameless.
*
* Reported bug:
* Face-up morph creatures that are bounced by Reflector Mage should be able to be replayed as morphs
* without the "until the next turn" restriction."
*
* Reflector Mage bouncing a creature that can be played as a morph should
* not prevent the card from being replayed as a morph. Morph creatures are
* nameless.
*
* Reported bug: Face-up morph creatures that are bounced by Reflector Mage
* should be able to be replayed as morphs without the "until the next turn"
* restriction."
*
* Testing bouncing a face-down creature played next turn face-up.
*/
@Test
public void testReflectorMageBouncesMorphCreatureReplayAsFaceup() {
//Tap: Add {G}, {U}, or {R} to your mana pool.
// Morph 2 (You may cast this card face down as a 2/2 creature for 3. Turn it face up any time for its morph cost.)
// When Rattleclaw Mystic is turned face up, add {G}{U}{R} to your mana pool.
@ -703,28 +707,28 @@ public class MorphTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerA, "Forest");
addCard(Zone.BATTLEFIELD, playerA, "Island");
addCard(Zone.BATTLEFIELD, playerA, "Mountain");
// {1}{W}{U} When Reflector Mage enters the battlefield, return target creature an opponent controls to its owner's hand.
// {1}{W}{U} When Reflector Mage enters the battlefield, return target creature an opponent controls to its owner's hand.
// That creature's owner can't cast spells with the same name as that creature until your next turn.
addCard(Zone.HAND, playerB, "Reflector Mage"); // 2/3
addCard(Zone.BATTLEFIELD, playerB, "Plains", 2);
addCard(Zone.BATTLEFIELD, playerB, "Island", 2);
addCard(Zone.HAND, playerB, "Reflector Mage"); // 2/3
addCard(Zone.BATTLEFIELD, playerB, "Plains", 2);
addCard(Zone.BATTLEFIELD, playerB, "Island", 2);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Rattleclaw Mystic");
setChoice(playerA, "Yes"); // cast it face down as 2/2 creature
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Reflector Mage");
addTarget(playerB, "");
castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Rattleclaw Mystic");
setChoice(playerA, "No"); // cast it face down as 2/2 creature
setStopAt(3, PhaseStep.BEGIN_COMBAT);
execute();
assertPermanentCount(playerB, "Reflector Mage", 1);
assertPermanentCount(playerA, "Rattleclaw Mystic", 1);
assertPermanentCount(playerB, "Reflector Mage", 1);
assertPermanentCount(playerA, "Rattleclaw Mystic", 1);
assertHandCount(playerA, "Rattleclaw Mystic", 0); // should have been replayed faceup
}
}

View file

@ -25,7 +25,6 @@
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package org.mage.test.cards.abilities.keywords;
import mage.constants.PhaseStep;
@ -38,15 +37,13 @@ import org.mage.test.serverside.base.CardTestPlayerBase;
*
* @author LevelX2
*/
public class ProliferateTest extends CardTestPlayerBase{
public class ProliferateTest extends CardTestPlayerBase {
/**
* Volt Charge {2}{R}
* Instant
* Volt Charge deals 3 damage to target creature or player.
* Proliferate. (You choose any number of permanents and/or players with counters
* on them, then give each another counter of a kind already there.)
* Volt Charge {2}{R} Instant Volt Charge deals 3 damage to target creature
* or player. Proliferate. (You choose any number of permanents and/or
* players with counters on them, then give each another counter of a kind
* already there.)
*/
@Test
public void testCastFromHandMovedToExile() {
@ -55,11 +52,9 @@ public class ProliferateTest extends CardTestPlayerBase{
addCard(Zone.HAND, playerA, "Volt Charge");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Volt Charge", playerB);
addTarget(playerA, "Chandra, Pyromaster");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
@ -69,19 +64,22 @@ public class ProliferateTest extends CardTestPlayerBase{
assertCounterCount("Chandra, Pyromaster", CounterType.LOYALTY, 5); // 4 + 1 from proliferate
}
/**
* Counters aren't cancelling each other out. Reproducible with any creature (graft and bloodthirst in my case)
* with a single +1/+1 counter on it, with a single -1/-1 placed on it (Grim Affliction, Instill Infection, etc).
* The counters should cancel each other out, leaving neither on the 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.
* Counters aren't cancelling each other out. Reproducible with any creature
* (graft and bloodthirst in my case) with a single +1/+1 counter on it,
* with a single -1/-1 placed on it (Grim Affliction, Instill Infection,
* etc). The counters should cancel each other out, leaving neither on the
* 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
public void testValidTargets() {
addCard(Zone.BATTLEFIELD, playerA, "Forest", 1);
addCard(Zone.BATTLEFIELD, playerA, "Island", 3);
addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion");
addCard(Zone.BATTLEFIELD, playerA, "Forest", 1);
addCard(Zone.BATTLEFIELD, playerA, "Island", 3);
addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion");
// Put a +1/+1 counter on target creature.
addCard(Zone.HAND, playerA, "Battlegrowth"); // {G}
// Proliferate. (You choose any number of permanents and/or players with counters on them, then give each another counter of a kind already there.)
@ -90,27 +88,27 @@ public class ProliferateTest extends CardTestPlayerBase{
addCard(Zone.BATTLEFIELD, playerB, "Sporeback Troll"); // has two +1/+1 counter
addCard(Zone.BATTLEFIELD, playerB, "Swamp", 3);
// Put a -1/-1 counter on target creature, then proliferate.
// Put a -1/-1 counter on target creature, then proliferate.
addCard(Zone.HAND, playerB, "Grim Affliction"); // {B}{2}
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Battlegrowth", "Silvercoat Lion");
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Grim Affliction", "Silvercoat Lion");
// proliferate Sporeback Troll
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerA, "Steady Progress");
// Silvercoat Lion may not be a valid target now
setStopAt(2, PhaseStep.BEGIN_COMBAT);
execute();
assertGraveyardCount(playerA, "Battlegrowth", 1);
assertGraveyardCount(playerA, "Steady Progress", 1);
assertGraveyardCount(playerB, "Grim Affliction", 1);
assertCounterCount("Silvercoat Lion", CounterType.P1P1, 0); // no valid target because no counter
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();
assertPermanentCount(playerA, "Elite Vanguard", 1);
assertCounterCount(playerA, "Elite Vanguard", CounterType.P1P1, 1);
assertPowerToughness(playerA, "Elite Vanguard", 3, 2);
}
@ -112,6 +113,7 @@ public class UndyingTest extends CardTestPlayerBase {
assertGraveyardCount(playerA, "Lightning Bolt", 1);
assertPermanentCount(playerB, "Strangleroot Geist", 0);
assertPermanentCount(playerA, "Strangleroot Geist", 1);
assertCounterCount(playerA, "Strangleroot Geist", CounterType.P1P1, 1);
assertPowerToughness(playerA, "Strangleroot Geist", 3, 2);
}
@ -211,6 +213,7 @@ public class UndyingTest extends CardTestPlayerBase {
assertPermanentCount(playerA, "Silvercoat Lion", 1);
assertPermanentCount(playerA, "Mikaeus, the Unhallowed", 1);
assertCounterCount(playerA, "Silvercoat Lion", CounterType.P1P1, 1);
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);
}
/**
* 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.Zone;
import mage.counters.CounterType;
import mage.game.permanent.Permanent;
import org.junit.Assert;
import org.junit.Test;
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
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");
// Put two 1/1 white Spirit creature tokens with flying onto the battlefield.
// Flashback {1}{B}
addCard(Zone.GRAVEYARD, playerA, "Lingering Souls");
setChoice(playerA, "Black");

View file

@ -381,7 +381,9 @@ public class TestPlayer implements Player {
@Override
public boolean priority(Game game) {
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.getAction().startsWith("activate:")) {
@ -478,7 +480,7 @@ public class TestPlayer implements Player {
int turns = Integer.parseUnsignedInt(groups[1].substring(6));
game.rollbackTurns(turns);
actions.remove(action);
break;
return true;
}
}
}

View file

@ -24,8 +24,7 @@
* 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;
import java.io.Serializable;
@ -49,15 +48,28 @@ public class MageInt implements Serializable, Copyable<MageInt> {
};
protected int baseValue;
protected int baseValueModified;
protected int boostedValue;
protected String cardValue = "";
public MageInt(int value) {
this.baseValue = value;
this.baseValueModified = baseValue;
this.boostedValue = baseValue;
this.cardValue = Integer.toString(value);
}
public MageInt(int baseValue, String cardValue) {
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;
}
@ -66,24 +78,37 @@ public class MageInt implements Serializable, Copyable<MageInt> {
if (this == EmptyMageInt) {
return this;
}
return new MageInt(baseValue, cardValue);
return new MageInt(baseValue, baseValueModified, boostedValue, cardValue);
}
public int getValue() {
public int getBaseValue() {
return baseValue;
}
public void initValue(int value) {
this.baseValue = value;
public int getBaseValueModified() {
return baseValueModified;
}
public int getValue() {
return boostedValue;
}
public void modifyBaseValue(int value) {
this.baseValueModified = value;
this.boostedValue = value;
this.cardValue = Integer.toString(value);
}
public void setValue(int value) {
this.baseValue = value;
this.boostedValue = value;
}
public void boostValue(int amount) {
this.baseValue += amount;
this.boostedValue += amount;
}
public void resetToBaseValue() {
this.boostedValue = this.baseValueModified;
}
@Override

View file

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

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
*/
public class CantAttackAloneEffect extends RestrictionEffect {
public class CantAttackAloneSourceEffect extends RestrictionEffect {
public CantAttackAloneEffect() {
public CantAttackAloneSourceEffect() {
super(Duration.WhileOnBattlefield);
staticText = "{this} can't attack alone";
}
public CantAttackAloneEffect(final CantAttackAloneEffect effect) {
public CantAttackAloneSourceEffect(final CantAttackAloneSourceEffect effect) {
super(effect);
}
@Override
public CantAttackAloneEffect copy() {
return new CantAttackAloneEffect(this);
public CantAttackAloneSourceEffect copy() {
return new CantAttackAloneSourceEffect(this);
}
@Override

View file

@ -47,13 +47,12 @@ import mage.game.Game;
import mage.game.permanent.Permanent;
/**
* This effect lets the card be a 2/2 face-down creature, with no text,
* no name, no subtypes, and no mana cost, if it's face down on the battlefield.
* And it adds the a TurnFaceUpAbility ability.
*
* This effect lets the card be a 2/2 face-down creature, with no text, no name,
* no subtypes, and no mana cost, if it's face down on the battlefield. And it
* adds the a TurnFaceUpAbility ability.
*
* @author LevelX2
*/
public class BecomesFaceDownCreatureEffect extends ContinuousEffectImpl implements SourceEffect {
public enum FaceDownType {
@ -65,15 +64,15 @@ public class BecomesFaceDownCreatureEffect extends ContinuousEffectImpl implemen
protected int zoneChangeCounter;
protected Ability turnFaceUpAbility = null;
protected MageObjectReference objectReference= null;
protected MageObjectReference objectReference = null;
protected boolean foundPermanent;
protected FaceDownType faceDownType;
public BecomesFaceDownCreatureEffect(Duration duration, FaceDownType faceDownType){
public BecomesFaceDownCreatureEffect(Duration duration, FaceDownType faceDownType) {
this(null, null, duration, faceDownType);
}
public BecomesFaceDownCreatureEffect(Costs<Cost> turnFaceUpCosts, FaceDownType faceDownType){
public BecomesFaceDownCreatureEffect(Costs<Cost> turnFaceUpCosts, FaceDownType faceDownType) {
this(turnFaceUpCosts, null, faceDownType);
}
@ -97,7 +96,6 @@ public class BecomesFaceDownCreatureEffect extends ContinuousEffectImpl implemen
this.faceDownType = faceDownType;
}
public BecomesFaceDownCreatureEffect(final BecomesFaceDownCreatureEffect effect) {
super(effect);
this.zoneChangeCounter = effect.zoneChangeCounter;
@ -147,11 +145,11 @@ public class BecomesFaceDownCreatureEffect extends ContinuousEffectImpl implemen
} else {
permanent = game.getPermanent(source.getSourceId());
}
if (permanent != null && permanent.isFaceDown(game)) {
if (!foundPermanent) {
foundPermanent = true;
switch(faceDownType) {
switch (faceDownType) {
case MANIFESTED:
case MANUAL: // sets manifested image
permanent.setManifested(true);
@ -184,11 +182,9 @@ public class BecomesFaceDownCreatureEffect extends ContinuousEffectImpl implemen
if (ability.getWorksFaceDown()) {
ability.setRuleVisible(false);
continue;
} else {
if (!ability.getRuleVisible() && !ability.getEffects().isEmpty()) {
if (ability.getEffects().get(0) instanceof BecomesFaceDownCreatureEffect) {
continue;
}
} else if (!ability.getRuleVisible() && !ability.getEffects().isEmpty()) {
if (ability.getEffects().get(0) instanceof BecomesFaceDownCreatureEffect) {
continue;
}
}
abilitiesToRemove.add(ability);
@ -200,14 +196,12 @@ public class BecomesFaceDownCreatureEffect extends ContinuousEffectImpl implemen
break;
case PTChangingEffects_7:
if (sublayer == SubLayer.SetPT_7b) {
permanent.getPower().setValue(2);
permanent.getToughness().setValue(2);
// permanent.getPower().setValue(2);
// permanent.getToughness().setValue(2);
}
}
} else {
if (duration.equals(Duration.Custom) && foundPermanent == true) {
discard();
}
} else if (duration.equals(Duration.Custom) && foundPermanent == true) {
discard();
}
return true;
}

View file

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

View file

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

View file

@ -75,6 +75,7 @@ public class FlashbackAbility extends SpellAbility {
this.timing = timingRule;
this.usesStack = false;
this.spellAbilityType = SpellAbilityType.BASE_ALTERNATE;
setCostModificationActive(false);
}
public FlashbackAbility(final FlashbackAbility ability) {
@ -195,7 +196,9 @@ class FlashbackEffect extends OneShotEffect {
spellAbility.clear();
// set the payed flashback costs to the spell ability so abilities like Converge or calculation of {X} values work
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
for (Cost cost : source.getCosts()) {
if (!(cost instanceof VariableCost)) {
@ -205,7 +208,6 @@ class FlashbackEffect extends OneShotEffect {
if (!game.isSimulation()) {
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)) {
ContinuousEffect effect = new FlashbackReplacementEffect();
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) {
mageObject.getPower().initValue(2);
mageObject.getToughness().initValue(2);
mageObject.getPower().modifyBaseValue(2);
mageObject.getToughness().modifyBaseValue(2);
mageObject.getAbilities().clear();
mageObject.getColor(null).setColor(new ObjectColor());
mageObject.setName("");

View file

@ -166,4 +166,13 @@ public enum CounterType {
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) {
power = card.getPower().copy();
toughness = card.getToughness().copy();
copyFromCard(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());
@ -94,6 +96,8 @@ public class PermanentCard extends PermanentImpl {
// 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
copyFromCard(card);
power.resetToBaseValue();
toughness.resetToBaseValue();
super.reset(game);
}
@ -115,8 +119,6 @@ public class PermanentCard extends PermanentImpl {
this.cardType.addAll(card.getCardType());
this.color = card.getColor(null).copy();
this.manaCost = card.getManaCost().copy();
this.power = card.getPower().copy();
this.toughness = card.getToughness().copy();
if (card instanceof PermanentCard) {
this.maxLevelCounters = ((PermanentCard) card).maxLevelCounters;
}
@ -232,6 +234,8 @@ public class PermanentCard extends PermanentImpl {
@Override
public boolean turnFaceUp(Game game, UUID playerId) {
if (super.turnFaceUp(game, playerId)) {
power.modifyBaseValue(power.getBaseValue());
toughness.modifyBaseValue(toughness.getBaseValue());
setManifested(false);
setMorphed(false);
return true;
@ -241,7 +245,7 @@ public class PermanentCard extends PermanentImpl {
@Override
public void adjustTargets(Ability ability, Game game) {
if (this.isTransformed()) {
if (this.isTransformed() && card.getSecondCardFace() != null) {
card.getSecondCardFace().adjustTargets(ability, game);
} else {
card.adjustTargets(ability, game);
@ -250,7 +254,7 @@ public class PermanentCard extends PermanentImpl {
@Override
public void adjustCosts(Ability ability, Game game) {
if (this.isTransformed()) {
if (this.isTransformed() && card.getSecondCardFace() != null) {
card.getSecondCardFace().adjustCosts(ability, game);
} else {
card.adjustCosts(ability, game);

View file

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

View file

@ -81,11 +81,11 @@ public class Token extends MageObjectImpl {
this.name = name;
this.description = description;
}
public Token(String name, String description, int power, int toughness) {
this(name, description);
this.power.setValue(power);
this.toughness.setValue(toughness);
this.power.modifyBaseValue(power);
this.toughness.modifyBaseValue(toughness);
}
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.color = color.copy();
this.subtype = subtype;
this.power.setValue(power);
this.toughness.setValue(toughness);
this.power.modifyBaseValue(power);
this.toughness.modifyBaseValue(toughness);
if (abilities != null) {
this.abilities = abilities.copy();
}
@ -217,11 +217,11 @@ public class Token extends MageObjectImpl {
}
return false;
}
public void setPower(int power) {
this.power.setValue(power);
}
public void setToughness(int toughness) {
this.toughness.setValue(toughness);
}
@ -264,17 +264,13 @@ public class Token extends MageObjectImpl {
if (availableImageSetCodes.size() > 0) {
if (availableImageSetCodes.contains(code)) {
setOriginalExpansionSetCode(code);
} else {
// we should not set random set if appropriate set is already used
if (getOriginalExpansionSetCode() == null || getOriginalExpansionSetCode().isEmpty()
|| !availableImageSetCodes.contains(getOriginalExpansionSetCode())) {
setOriginalExpansionSetCode(availableImageSetCodes.get(new Random().nextInt(availableImageSetCodes.size())));
}
}
} else {
if (getOriginalExpansionSetCode() == null || getOriginalExpansionSetCode().isEmpty()) {
setOriginalExpansionSetCode(code);
} else // we should not set random set if appropriate set is already used
if (getOriginalExpansionSetCode() == null || getOriginalExpansionSetCode().isEmpty()
|| !availableImageSetCodes.contains(getOriginalExpansionSetCode())) {
setOriginalExpansionSetCode(availableImageSetCodes.get(new Random().nextInt(availableImageSetCodes.size())));
}
} else if (getOriginalExpansionSetCode() == null || getOriginalExpansionSetCode().isEmpty()) {
setOriginalExpansionSetCode(code);
}
}

View file

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

View file

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

View file

@ -108,9 +108,9 @@ public class CopyTokenFunction implements Function<Token, Card> {
ability.setSourceId(target.getId());
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.getToughness().initValue(Integer.parseInt(sourceObj.getToughness().toString()));
target.getPower().modifyBaseValue(sourceObj.getPower().getBaseValueModified());
target.getToughness().modifyBaseValue(sourceObj.getToughness().getBaseValueModified());
return target;
}